@@ -0,0 +1,247 @@
|
||||
package org.raddatz.familienarchiv.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.raddatz.familienarchiv.dto.CreateAnnotationDTO;
|
||||
import org.raddatz.familienarchiv.dto.CreateTranscriptionBlockDTO;
|
||||
import org.raddatz.familienarchiv.dto.ReorderTranscriptionBlocksDTO;
|
||||
import org.raddatz.familienarchiv.dto.UpdateTranscriptionBlockDTO;
|
||||
import org.raddatz.familienarchiv.exception.DomainException;
|
||||
import org.raddatz.familienarchiv.model.Document;
|
||||
import org.raddatz.familienarchiv.model.DocumentAnnotation;
|
||||
import org.raddatz.familienarchiv.model.TranscriptionBlock;
|
||||
import org.raddatz.familienarchiv.model.TranscriptionBlockVersion;
|
||||
import org.raddatz.familienarchiv.repository.AnnotationRepository;
|
||||
import org.raddatz.familienarchiv.repository.TranscriptionBlockRepository;
|
||||
import org.raddatz.familienarchiv.repository.TranscriptionBlockVersionRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TranscriptionServiceTest {
|
||||
|
||||
@Mock TranscriptionBlockRepository blockRepository;
|
||||
@Mock TranscriptionBlockVersionRepository versionRepository;
|
||||
@Mock AnnotationRepository annotationRepository;
|
||||
@Mock AnnotationService annotationService;
|
||||
@Mock DocumentService documentService;
|
||||
@InjectMocks TranscriptionService transcriptionService;
|
||||
|
||||
// ─── getBlock ────────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void getBlock_throwsNotFound_whenBlockDoesNotExist() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> transcriptionService.getBlock(docId, blockId))
|
||||
.isInstanceOf(DomainException.class)
|
||||
.satisfies(e -> assertThat(((DomainException) e).getStatus()).isEqualTo(NOT_FOUND));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBlock_returnsBlock_whenExists() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
TranscriptionBlock block = TranscriptionBlock.builder()
|
||||
.id(blockId).documentId(docId).text("hello").build();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block));
|
||||
|
||||
TranscriptionBlock result = transcriptionService.getBlock(docId, blockId);
|
||||
|
||||
assertThat(result).isEqualTo(block);
|
||||
}
|
||||
|
||||
// ─── createBlock ─────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void createBlock_createsAnnotationAndBlockAndVersion() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID userId = UUID.randomUUID();
|
||||
UUID annotId = UUID.randomUUID();
|
||||
|
||||
Document doc = Document.builder().id(docId).fileHash("hash123").build();
|
||||
when(documentService.getDocumentById(docId)).thenReturn(doc);
|
||||
|
||||
DocumentAnnotation annotation = DocumentAnnotation.builder().id(annotId).build();
|
||||
when(annotationService.createAnnotation(eq(docId), any(CreateAnnotationDTO.class), eq(userId), eq("hash123")))
|
||||
.thenReturn(annotation);
|
||||
|
||||
when(blockRepository.countByDocumentId(docId)).thenReturn(0);
|
||||
when(blockRepository.save(any())).thenAnswer(inv -> {
|
||||
TranscriptionBlock b = inv.getArgument(0);
|
||||
b.setId(UUID.randomUUID());
|
||||
return b;
|
||||
});
|
||||
|
||||
CreateTranscriptionBlockDTO dto = new CreateTranscriptionBlockDTO(1, 0.1, 0.2, 0.3, 0.4, "hello", null);
|
||||
|
||||
TranscriptionBlock result = transcriptionService.createBlock(docId, dto, userId);
|
||||
|
||||
assertThat(result.getAnnotationId()).isEqualTo(annotId);
|
||||
assertThat(result.getText()).isEqualTo("hello");
|
||||
assertThat(result.getSortOrder()).isZero();
|
||||
assertThat(result.getCreatedBy()).isEqualTo(userId);
|
||||
verify(versionRepository).save(any(TranscriptionBlockVersion.class));
|
||||
}
|
||||
|
||||
// ─── updateBlock ─────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void updateBlock_updatesTextAndSavesVersion() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
UUID userId = UUID.randomUUID();
|
||||
|
||||
TranscriptionBlock block = TranscriptionBlock.builder()
|
||||
.id(blockId).documentId(docId).text("old").build();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block));
|
||||
when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
|
||||
UpdateTranscriptionBlockDTO dto = new UpdateTranscriptionBlockDTO("new text", null);
|
||||
|
||||
TranscriptionBlock result = transcriptionService.updateBlock(docId, blockId, dto, userId);
|
||||
|
||||
assertThat(result.getText()).isEqualTo("new text");
|
||||
assertThat(result.getUpdatedBy()).isEqualTo(userId);
|
||||
verify(versionRepository).save(any(TranscriptionBlockVersion.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateBlock_updatesLabel_whenProvided() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
|
||||
TranscriptionBlock block = TranscriptionBlock.builder()
|
||||
.id(blockId).documentId(docId).text("text").label("old label").build();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block));
|
||||
when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
|
||||
UpdateTranscriptionBlockDTO dto = new UpdateTranscriptionBlockDTO("text", "Anrede");
|
||||
|
||||
TranscriptionBlock result = transcriptionService.updateBlock(docId, blockId, dto, UUID.randomUUID());
|
||||
|
||||
assertThat(result.getLabel()).isEqualTo("Anrede");
|
||||
}
|
||||
|
||||
// ─── deleteBlock ─────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void deleteBlock_deletesBlockAndAnnotation() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
UUID annotId = UUID.randomUUID();
|
||||
|
||||
TranscriptionBlock block = TranscriptionBlock.builder()
|
||||
.id(blockId).documentId(docId).annotationId(annotId).build();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block));
|
||||
|
||||
transcriptionService.deleteBlock(docId, blockId);
|
||||
|
||||
verify(blockRepository).delete(block);
|
||||
verify(blockRepository).flush();
|
||||
verify(annotationRepository).deleteById(annotId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteBlock_throwsNotFound_whenBlockMissing() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> transcriptionService.deleteBlock(docId, blockId))
|
||||
.isInstanceOf(DomainException.class)
|
||||
.satisfies(e -> assertThat(((DomainException) e).getStatus()).isEqualTo(NOT_FOUND));
|
||||
}
|
||||
|
||||
// ─── reorderBlocks ───────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void reorderBlocks_updatesSortOrder() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID id1 = UUID.randomUUID();
|
||||
UUID id2 = UUID.randomUUID();
|
||||
|
||||
TranscriptionBlock block1 = TranscriptionBlock.builder()
|
||||
.id(id1).documentId(docId).sortOrder(0).build();
|
||||
TranscriptionBlock block2 = TranscriptionBlock.builder()
|
||||
.id(id2).documentId(docId).sortOrder(1).build();
|
||||
|
||||
when(blockRepository.findByIdAndDocumentId(id2, docId)).thenReturn(Optional.of(block2));
|
||||
when(blockRepository.findByIdAndDocumentId(id1, docId)).thenReturn(Optional.of(block1));
|
||||
when(blockRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
||||
when(blockRepository.findByDocumentIdOrderBySortOrderAsc(docId)).thenReturn(List.of(block2, block1));
|
||||
|
||||
ReorderTranscriptionBlocksDTO dto = new ReorderTranscriptionBlocksDTO(List.of(id2, id1));
|
||||
|
||||
transcriptionService.reorderBlocks(docId, dto);
|
||||
|
||||
assertThat(block2.getSortOrder()).isZero();
|
||||
assertThat(block1.getSortOrder()).isEqualTo(1);
|
||||
}
|
||||
|
||||
// ─── getBlockHistory ─────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void getBlockHistory_returnsVersionsForBlock() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
UUID blockId = UUID.randomUUID();
|
||||
|
||||
TranscriptionBlock block = TranscriptionBlock.builder()
|
||||
.id(blockId).documentId(docId).build();
|
||||
when(blockRepository.findByIdAndDocumentId(blockId, docId)).thenReturn(Optional.of(block));
|
||||
|
||||
TranscriptionBlockVersion v = TranscriptionBlockVersion.builder()
|
||||
.id(UUID.randomUUID()).blockId(blockId).text("ver1").build();
|
||||
when(versionRepository.findByBlockIdOrderByChangedAtDesc(blockId)).thenReturn(List.of(v));
|
||||
|
||||
List<TranscriptionBlockVersion> result = transcriptionService.getBlockHistory(docId, blockId);
|
||||
|
||||
assertThat(result).containsExactly(v);
|
||||
}
|
||||
|
||||
// ─── sanitizeText ────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void sanitizeText_returnsEmptyString_forNull() {
|
||||
assertThat(transcriptionService.sanitizeText(null)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void sanitizeText_truncatesAtMaxLength() {
|
||||
String longText = "a".repeat(15_000);
|
||||
String result = transcriptionService.sanitizeText(longText);
|
||||
assertThat(result).hasSize(10_000);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sanitizeText_preservesPlainText() {
|
||||
assertThat(transcriptionService.sanitizeText("Liebe Mutter,")).isEqualTo("Liebe Mutter,");
|
||||
}
|
||||
|
||||
// ─── listBlocks ──────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
void listBlocks_returnsBlocksOrderedBySortOrder() {
|
||||
UUID docId = UUID.randomUUID();
|
||||
TranscriptionBlock b = TranscriptionBlock.builder()
|
||||
.id(UUID.randomUUID()).documentId(docId).sortOrder(0).build();
|
||||
when(blockRepository.findByDocumentIdOrderBySortOrderAsc(docId)).thenReturn(List.of(b));
|
||||
|
||||
assertThat(transcriptionService.listBlocks(docId)).containsExactly(b);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user