feat: add task creation board

This commit is contained in:
Urban Modig
2026-07-25 10:31:37 +02:00
parent 050f248857
commit 3f152eeccc
16 changed files with 962 additions and 29 deletions

View File

@ -0,0 +1,107 @@
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.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 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.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
class TaskApiTest {
@Autowired
private WebApplicationContext context;
@Autowired
private TaskRepository taskRepository;
private MockMvc mockMvc;
@BeforeEach
void setUp() {
taskRepository.deleteAll();
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
void createsWaitingTaskWithTrimmedValues() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": " Dammsuga ",
"description": " Bottenvåningen "
}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id").isString())
.andExpect(jsonPath("$.title").value("Dammsuga"))
.andExpect(jsonPath("$.description").value("Bottenvåningen"))
.andExpect(jsonPath("$.status").value("WAITING"))
.andExpect(jsonPath("$.createdAt").isString());
}
@Test
void storesBlankDescriptionAsNull() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"title": "Dammsuga", "description": " "}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.description").value((Object) null));
}
@Test
void rejectsBlankAndTooLongTitles() throws Exception {
assertInvalidTask("""
{"title": " "}
""");
assertInvalidTask("{\"title\": \"%s\"}".formatted("a".repeat(101)));
}
@Test
void rejectsTooLongDescription() throws Exception {
assertInvalidTask("""
{"title": "Dammsuga", "description": "%s"}
""".formatted("a".repeat(501)));
}
@Test
void listsTasksOldestFirstWithIdAsTieBreaker() throws Exception {
Instant older = Instant.parse("2026-07-24T10:00:00Z");
Instant newer = Instant.parse("2026-07-24T11:00:00Z");
UUID firstId = UUID.fromString("00000000-0000-0000-0000-000000000001");
UUID secondId = UUID.fromString("00000000-0000-0000-0000-000000000002");
UUID newestId = UUID.fromString("00000000-0000-0000-0000-000000000003");
taskRepository.save(new Task(newestId, "Nyast", null, TaskStatus.WAITING, newer));
taskRepository.save(new Task(secondId, "Andra", null, TaskStatus.IN_PROGRESS, older));
taskRepository.save(new Task(firstId, "Första", null, TaskStatus.COMPLETED, older));
mockMvc.perform(get("/api/tasks"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].title").value("Första"))
.andExpect(jsonPath("$[1].title").value("Andra"))
.andExpect(jsonPath("$[2].title").value("Nyast"));
}
private void assertInvalidTask(String body) throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content(body))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("INVALID_TASK"));
}
}