diff --git a/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte b/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte index 1dc5b660..4579e762 100644 --- a/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte +++ b/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte @@ -14,7 +14,10 @@ interface Props { let { personId, relationships, inferredRelationships }: Props = $props(); -const topDerived = $derived(inferredRelationships.slice(0, 5)); +const directOtherIds = $derived(new Set(relationships.map((rel) => otherId(rel)))); +const topDerived = $derived( + inferredRelationships.filter((d) => !directOtherIds.has(d.person.id)).slice(0, 5) +); function chipLabel(rel: RelationshipDTO): string { const viewpointIsSubject = rel.personId === personId; diff --git a/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte.test.ts b/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte.test.ts new file mode 100644 index 00000000..b0a13ef6 --- /dev/null +++ b/frontend/src/routes/persons/[id]/PersonRelationshipsCard.svelte.test.ts @@ -0,0 +1,56 @@ +import { describe, it, expect } from 'vitest'; +import { render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import PersonRelationshipsCard from './PersonRelationshipsCard.svelte'; + +const PERSON_ID = '00000000-0000-0000-0000-000000000001'; +const SPOUSE_ID = '00000000-0000-0000-0000-000000000002'; + +describe('PersonRelationshipsCard', () => { + it('hides an inferred relationship that is already a direct one', async () => { + render(PersonRelationshipsCard, { + personId: PERSON_ID, + relationships: [ + { + id: 'r1', + personId: PERSON_ID, + relatedPersonId: SPOUSE_ID, + personDisplayName: 'Anna Müller', + relatedPersonDisplayName: 'Bertha Müller', + relationType: 'SPOUSE_OF' + } + ], + inferredRelationships: [ + { + person: { + id: SPOUSE_ID, + displayName: 'Bertha Müller', + familyMember: true + }, + label: 'SPOUSE', + hops: 1 + } + ] + }); + + const matches = await page.getByText('Bertha Müller').all(); + expect(matches).toHaveLength(1); + }); + + it('still renders inferred relationships that are not direct', async () => { + const COUSIN_ID = '00000000-0000-0000-0000-000000000003'; + render(PersonRelationshipsCard, { + personId: PERSON_ID, + relationships: [], + inferredRelationships: [ + { + person: { id: COUSIN_ID, displayName: 'Carla Cousine', familyMember: true }, + label: 'COUSIN', + hops: 4 + } + ] + }); + + await expect.element(page.getByText('Carla Cousine')).toBeInTheDocument(); + }); +});