test(transcription): round-trip TranscriptionBlock.mentionedPersons

@DataJpaTest + Testcontainers exercises the V56 migration plus the
@ElementCollection wiring end-to-end. Saves a block with two PersonMention
entries, clears the persistence context, reloads, asserts both entries
return with their personId + displayName intact. Second test guards the
@Builder.Default — a block without explicit mentions reloads with an empty
list, not null.

Refs #362

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-28 20:07:56 +02:00
parent 0f3e000379
commit 7805da52e6

View File

@@ -0,0 +1,95 @@
package org.raddatz.familienarchiv.repository;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.config.FlywayConfig;
import org.raddatz.familienarchiv.model.Document;
import org.raddatz.familienarchiv.model.DocumentAnnotation;
import org.raddatz.familienarchiv.model.DocumentStatus;
import org.raddatz.familienarchiv.model.PersonMention;
import org.raddatz.familienarchiv.model.TranscriptionBlock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.context.annotation.Import;
import java.util.List;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import({PostgresContainerConfig.class, FlywayConfig.class})
class TranscriptionBlockMentionsRepositoryTest {
@Autowired TranscriptionBlockRepository blockRepository;
@Autowired DocumentRepository documentRepository;
@Autowired AnnotationRepository annotationRepository;
@Autowired EntityManager em;
private UUID documentId;
private UUID annotationId;
@BeforeEach
void setUp() {
Document doc = documentRepository.save(Document.builder()
.title("Letter")
.originalFilename("letter.pdf")
.status(DocumentStatus.UPLOADED)
.build());
documentId = doc.getId();
DocumentAnnotation annotation = annotationRepository.save(DocumentAnnotation.builder()
.documentId(documentId)
.pageNumber(1)
.x(0.1).y(0.2).width(0.3).height(0.4)
.color("#00C7B1")
.build());
annotationId = annotation.getId();
}
@Test
void mentionedPersons_roundTripsTwoEntries() {
UUID auguste = UUID.randomUUID();
UUID hermann = UUID.randomUUID();
TranscriptionBlock saved = blockRepository.saveAndFlush(TranscriptionBlock.builder()
.annotationId(annotationId)
.documentId(documentId)
.text("Liebe Tante @Auguste Raddatz, Onkel @Hermann Müller schreibt …")
.sortOrder(0)
.mentionedPersons(List.of(
new PersonMention(auguste, "Auguste Raddatz"),
new PersonMention(hermann, "Hermann Müller")
))
.build());
em.clear();
TranscriptionBlock reloaded = blockRepository.findById(saved.getId()).orElseThrow();
assertThat(reloaded.getMentionedPersons())
.extracting(PersonMention::getPersonId, PersonMention::getDisplayName)
.containsExactlyInAnyOrder(
org.assertj.core.groups.Tuple.tuple(auguste, "Auguste Raddatz"),
org.assertj.core.groups.Tuple.tuple(hermann, "Hermann Müller"));
}
@Test
void mentionedPersons_defaultsToEmptyList_whenNotSet() {
TranscriptionBlock saved = blockRepository.saveAndFlush(TranscriptionBlock.builder()
.annotationId(annotationId)
.documentId(documentId)
.text("Plain text without mentions")
.sortOrder(0)
.build());
em.clear();
TranscriptionBlock reloaded = blockRepository.findById(saved.getId()).orElseThrow();
assertThat(reloaded.getMentionedPersons()).isEmpty();
}
}