From 8adc39e2cea503b02bc8a6fd8eb6946c7916063d Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 9 Jun 2026 18:51:51 +0200 Subject: [PATCH] test(geschichte): add integration tests for documentId JPQL EXISTS filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verifies the EXISTS subquery in findSummaries actually filters by document membership — a journey containing the document appears, one without does not. Co-Authored-By: Claude Sonnet 4.6 --- .../GeschichteListProjectionTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteListProjectionTest.java b/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteListProjectionTest.java index 3c1cefcf..ff2dc68d 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteListProjectionTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/geschichte/GeschichteListProjectionTest.java @@ -4,6 +4,11 @@ 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.document.Document; +import org.raddatz.familienarchiv.document.DocumentRepository; +import org.raddatz.familienarchiv.document.DocumentStatus; +import org.raddatz.familienarchiv.geschichte.journeyitem.JourneyItem; +import org.raddatz.familienarchiv.geschichte.journeyitem.JourneyItemRepository; import org.raddatz.familienarchiv.person.Person; import org.raddatz.familienarchiv.person.PersonRepository; import org.raddatz.familienarchiv.user.AppUser; @@ -27,6 +32,8 @@ class GeschichteListProjectionTest { @Autowired GeschichteRepository geschichteRepository; @Autowired AppUserRepository appUserRepository; @Autowired PersonRepository personRepository; + @Autowired DocumentRepository documentRepository; + @Autowired JourneyItemRepository journeyItemRepository; AppUser author; AppUser otherAuthor; @@ -170,6 +177,35 @@ class GeschichteListProjectionTest { assertThat(result.get(0).getTitle()).isEqualTo("Both"); } + // ─── documentId filter (JPQL EXISTS subquery) ──────────────────────────── + + @Test + void findSummaries_with_documentId_returns_journey_containing_that_document() { + Document doc = documentRepository.save(Document.builder() + .title("Brief").originalFilename("brief.pdf").status(DocumentStatus.UPLOADED).build()); + Geschichte withDoc = geschichteRepository.save(journey("Reise mit Dokument", author)); + Geschichte withoutDoc = geschichteRepository.save(journey("Reise ohne Dokument", author)); + journeyItemRepository.save(JourneyItem.builder() + .geschichte(withDoc).document(doc).position(1).build()); + + List result = geschichteRepository.findSummaries( + GeschichteStatus.PUBLISHED, null, sentinel(), 0, doc.getId()); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getTitle()).isEqualTo("Reise mit Dokument"); + assertThat(result).extracting(GeschichteSummary::getTitle).doesNotContain("Reise ohne Dokument"); + } + + @Test + void findSummaries_with_unknown_documentId_returns_empty() { + geschichteRepository.save(journey("Irgendeine Reise", author)); + + List result = geschichteRepository.findSummaries( + GeschichteStatus.PUBLISHED, null, sentinel(), 0, UUID.randomUUID()); + + assertThat(result).isEmpty(); + } + // ─── helpers ───────────────────────────────────────────────────────────── private Geschichte published(String title, AppUser writer) { @@ -189,6 +225,16 @@ class GeschichteListProjectionTest { .build(); } + private Geschichte journey(String title, AppUser writer) { + return Geschichte.builder() + .title(title) + .status(GeschichteStatus.PUBLISHED) + .type(GeschichteType.JOURNEY) + .author(writer) + .publishedAt(LocalDateTime.now()) + .build(); + } + /** Sentinel UUID passed when personCount=0 — the IN() clause is never evaluated. */ private List sentinel() { return List.of(UUID.fromString("00000000-0000-0000-0000-000000000000"));