From e94ffde075d0a15ef6b22f78a1e39725b066e291 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 28 Apr 2026 20:28:25 +0200 Subject: [PATCH] test(transcription): partial-name collision does not corrupt unrenamed mention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Block contains both @Hans-Peter Müller and @Hans Müller; the listener fires a rename for Hans Müller → Hans Schmidt. The simple replace("@" + old, "@" + new) hinges on the leading @-and-space anchor: "@Hans Müller" does not appear inside "@Hans-Peter Müller" (hyphen interrupts), so only the standalone mention rewrites. Sidecar mirrors the same — Hans Müller's entry flips to Hans Schmidt while Hans-Peter Müller's entry is preserved. Refs #362 Co-Authored-By: Claude Opus 4.7 --- .../PersonMentionPropagationListenerTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/backend/src/test/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListenerTest.java b/backend/src/test/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListenerTest.java index 00243f9a..a1abbfa1 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListenerTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/service/PersonMentionPropagationListenerTest.java @@ -96,6 +96,32 @@ class PersonMentionPropagationListenerTest { .containsExactly("Augusta Raddatz"); } + @Test + void doesNotMatchPartialName_whenAnotherMentionShares_a_substring_with_renamed_person() { + UUID hansPeterId = savedPersonId("Hans-Peter", "Müller"); + UUID hansId = savedPersonId("Hans", "Müller"); + TranscriptionBlock saved = saveBlock( + "Heute hat @Hans-Peter Müller wieder mit @Hans Müller gesprochen.", + List.of( + new PersonMention(hansPeterId, "Hans-Peter Müller"), + new PersonMention(hansId, "Hans Müller"))); + em.clear(); + + listener.onPersonDisplayNameChanged( + new PersonDisplayNameChangedEvent(hansId, "Hans Müller", "Hans Schmidt")); + blockRepository.flush(); + em.clear(); + + TranscriptionBlock reloaded = blockRepository.findById(saved.getId()).orElseThrow(); + assertThat(reloaded.getText()) + .isEqualTo("Heute hat @Hans-Peter Müller wieder mit @Hans Schmidt gesprochen."); + assertThat(reloaded.getMentionedPersons()) + .extracting(PersonMention::getPersonId, PersonMention::getDisplayName) + .containsExactlyInAnyOrder( + org.assertj.core.groups.Tuple.tuple(hansPeterId, "Hans-Peter Müller"), + org.assertj.core.groups.Tuple.tuple(hansId, "Hans Schmidt")); + } + @Test void leavesUnrelatedBlockUntouched_whenNoSidecarReferencesPerson() { UUID personId = savedPersonId("Auguste", "Raddatz");