feat(comments): add block-level comment endpoints with TDD
RED/GREEN for CommentService:
- getCommentsForBlock(blockId): returns root comments filtered by blockId
- postBlockComment(documentId, blockId, content, mentions, author): creates
comment with block_id set
RED/GREEN for CommentController:
- GET /api/documents/{docId}/transcription-blocks/{blockId}/comments
- POST /api/documents/{docId}/transcription-blocks/{blockId}/comments
- POST .../comments/{commentId}/replies (reuses existing replyToComment)
4 new tests: 2 service unit tests + 2 controller integration tests
All 25 CommentServiceTest + 24 CommentControllerTest green
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -279,4 +279,30 @@ class CommentControllerTest {
|
||||
.contentType(MediaType.APPLICATION_JSON).content(COMMENT_JSON))
|
||||
.andExpect(status().isCreated());
|
||||
}
|
||||
|
||||
// ─── Block comment endpoints ─────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void getBlockComments_returns200() throws Exception {
|
||||
UUID blockId = UUID.randomUUID();
|
||||
when(commentService.getCommentsForBlock(blockId)).thenReturn(List.of());
|
||||
|
||||
mockMvc.perform(get("/api/documents/" + DOC_ID + "/transcription-blocks/" + blockId + "/comments"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "WRITE_ALL")
|
||||
void postBlockComment_returns201() throws Exception {
|
||||
UUID blockId = UUID.randomUUID();
|
||||
DocumentComment saved = DocumentComment.builder()
|
||||
.id(UUID.randomUUID()).documentId(DOC_ID).blockId(blockId).content("Nice").build();
|
||||
when(commentService.postBlockComment(any(), any(), any(), any(), any())).thenReturn(saved);
|
||||
|
||||
mockMvc.perform(post("/api/documents/" + DOC_ID + "/transcription-blocks/" + blockId + "/comments")
|
||||
.contentType(MediaType.APPLICATION_JSON).content(COMMENT_JSON))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.blockId").value(blockId.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,4 +488,40 @@ class CommentServiceTest {
|
||||
.build()))
|
||||
.build();
|
||||
}
|
||||
|
||||
// ─── Block-level comments ────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void getCommentsForBlock_returnsRootCommentsFilteredByBlockId() {
|
||||
UUID blockId = UUID.randomUUID();
|
||||
DocumentComment root = DocumentComment.builder()
|
||||
.id(UUID.randomUUID()).blockId(blockId).content("Nice work").authorName("Felix")
|
||||
.createdAt(LocalDateTime.now()).updatedAt(LocalDateTime.now()).build();
|
||||
when(commentRepository.findByBlockIdAndParentIdIsNull(blockId)).thenReturn(List.of(root));
|
||||
when(commentRepository.findByParentId(root.getId())).thenReturn(List.of());
|
||||
|
||||
List<DocumentComment> result = commentService.getCommentsForBlock(blockId);
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.getFirst().getContent()).isEqualTo("Nice work");
|
||||
}
|
||||
|
||||
@Test
|
||||
void postBlockComment_setsBlockIdOnComment() {
|
||||
UUID documentId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
AppUser author = AppUser.builder().id(UUID.randomUUID()).username("felix").firstName("Felix").lastName("Brandt").build();
|
||||
when(commentRepository.save(any())).thenAnswer(inv -> {
|
||||
DocumentComment c = inv.getArgument(0);
|
||||
c.setId(UUID.randomUUID());
|
||||
return c;
|
||||
});
|
||||
|
||||
DocumentComment result = commentService.postBlockComment(
|
||||
documentId, blockId, "Looks like Breslau", List.of(), author);
|
||||
|
||||
assertThat(result.getBlockId()).isEqualTo(blockId);
|
||||
assertThat(result.getDocumentId()).isEqualTo(documentId);
|
||||
assertThat(result.getContent()).isEqualTo("Looks like Breslau");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user