refactor(#248): address PR review concerns — TagOperator enum, typed projection, bean validation
- Replace stringly-typed "AND"/"OR" tagOperator with TagOperator enum (DocumentService, DocumentController) - Replace Object[] with TagCount projection interface in TagRepository.findDocumentCountsPerTag() - Use @NotNull + @Valid on MergeTagDTO.targetId; remove manual null check from TagController - Correct ALLOWED_TAG_COLORS to match actual frontend CSS tokens (sage/sienna/amber/slate/violet/rose/cobalt/moss/sand/coral) - Add TOCTOU comment to validateNoAncestorCycle() with mitigation explanation - Add test: deleteWithDescendants_skipsDocTagDeletion_whenDescendantIdsIsEmpty - Update TagServiceTest to use mock TagRepository.TagCount projection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@@ -256,8 +257,11 @@ class TagServiceTest {
|
||||
void getTagTree_populatesDocumentCount_fromAggregateQuery() {
|
||||
UUID tagId = UUID.randomUUID();
|
||||
Tag tag = Tag.builder().id(tagId).name("Tag").build();
|
||||
TagRepository.TagCount countEntry = mock(TagRepository.TagCount.class);
|
||||
when(countEntry.getTagId()).thenReturn(tagId);
|
||||
when(countEntry.getCount()).thenReturn(5L);
|
||||
when(tagRepository.findAll()).thenReturn(List.of(tag));
|
||||
when(tagRepository.findDocumentCountsPerTag()).thenReturn(List.<Object[]>of(new Object[]{tagId, 5L}));
|
||||
when(tagRepository.findDocumentCountsPerTag()).thenReturn(List.of(countEntry));
|
||||
|
||||
var tree = tagService.getTagTree();
|
||||
|
||||
@@ -456,6 +460,19 @@ class TagServiceTest {
|
||||
verify(tagRepository).deleteAllById(List.of(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteWithDescendants_skipsDocTagDeletion_whenDescendantIdsIsEmpty() {
|
||||
UUID id = UUID.randomUUID();
|
||||
Tag tag = Tag.builder().id(id).name("Tag").build();
|
||||
when(tagRepository.findById(id)).thenReturn(Optional.of(tag));
|
||||
when(tagRepository.findDescendantIds(id)).thenReturn(List.of());
|
||||
|
||||
tagService.deleteWithDescendants(id);
|
||||
|
||||
verify(tagRepository, never()).deleteDocumentTagsByTagIds(any());
|
||||
verify(tagRepository).deleteAllById(List.of());
|
||||
}
|
||||
|
||||
// ─── delete ───────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user