From da3067150d5ab1b1d8ca100356720e329f1d4bc4 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 31 May 2026 19:15:54 +0200 Subject: [PATCH] test(stammbaum): assert connector dimming at the render layer (#703 AC5) Sara/Elicit flagged that AC5 was proven only at the isConnectorActive predicate level. Add render-layer assertions: no connector group carries a dim opacity when nothing is selected, and selecting Vater dims exactly the vertical feeding the collateral child Tante. Exercises the shared parent-pair per-child wiring. Co-Authored-By: Claude Opus 4.8 --- .../genealogy/StammbaumTree.svelte.test.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/frontend/src/lib/person/genealogy/StammbaumTree.svelte.test.ts b/frontend/src/lib/person/genealogy/StammbaumTree.svelte.test.ts index 5434b971..3cdd45c7 100644 --- a/frontend/src/lib/person/genealogy/StammbaumTree.svelte.test.ts +++ b/frontend/src/lib/person/genealogy/StammbaumTree.svelte.test.ts @@ -965,6 +965,15 @@ describe('StammbaumTree lineage highlight (#703)', () => { } const DIM = String(DIMMED_OPACITY); + // Connector groups render as direct children; the node content groups + // (also .lineage-fade) are nested inside g[role="button"], so the child + // combinator scopes cleanly to connectors. + function dimmedConnectorCount(): number { + return Array.from(document.querySelectorAll('svg > g.lineage-fade')).filter( + (g) => g.getAttribute('opacity') === DIM + ).length; + } + it('renders every node at full strength when nothing is selected (AC1)', () => { render(StammbaumTree, { nodes: NODES, @@ -1047,4 +1056,33 @@ describe('StammbaumTree lineage highlight (#703)', () => { }); for (const n of NODES) expect(nodeOpacity(n.displayName)).toBeNull(); }); + + it('leaves every connector at full strength when nothing is selected (AC5)', () => { + render(StammbaumTree, { + nodes: NODES, + edges: EDGES, + selectedId: null, + panZoom: { x: 0, y: 0, z: 1 }, + showGutter: false, + onSelect: () => {} + }); + expect(dimmedConnectorCount()).toBe(0); + }); + + it('dims exactly the connector feeding the collateral child at the render layer (AC5)', () => { + render(StammbaumTree, { + nodes: NODES, + edges: EDGES, + selectedId: 'vater', + panZoom: { x: 0, y: 0, z: 1 }, + showGutter: false, + onSelect: () => {} + }); + // Every connector among the bloodline + spouses stays full strength; only + // the vertical joining the active parent pair (Grossvater+Grossmutter) to + // the dimmed collateral child (Tante) renders at DIMMED_OPACITY. This proves + // the render wiring — not just the isConnectorActive predicate — + // and exercises the shared parent-pair per-child path. + expect(dimmedConnectorCount()).toBe(1); + }); });