test(stammbaum): cross-level marriage records a distinct cross-link (#724)
When the two spouses' parents sit at different structural levels, the structural owner keeps its hierarchy edge and the other parent->spouse edge is recorded in layout.crossLinks (rendered with a distinct dash). The couple still sits exactly adjacent in the owner's run and B keeps a real position. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -364,3 +364,44 @@ describe('buildLayout — multi-spouse ordering (#361)', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('buildLayout — cross-level marriage fallback (#724)', () => {
|
||||||
|
// A bond is cross-level when the two spouses' parents sit at different
|
||||||
|
// structural levels. Adjacency cannot keep both connectors short, so the
|
||||||
|
// structural owner keeps its hierarchy edge and the other parent → spouse
|
||||||
|
// edge becomes a distinct cross-link.
|
||||||
|
const GP = '00000000-0000-0000-0000-0000000000e1'; // G0, deep branch ancestor
|
||||||
|
const P = '00000000-0000-0000-0000-0000000000e2'; // G1, child of GP
|
||||||
|
const A = '00000000-0000-0000-0000-0000000000e3'; // G2, child of P (nested deep)
|
||||||
|
const R = '00000000-0000-0000-0000-0000000000e4'; // G1 root
|
||||||
|
const B = '00000000-0000-0000-0000-0000000000e5'; // G2, child of R
|
||||||
|
|
||||||
|
it('records the displaced parent edge as a cross-link and keeps the couple adjacent', () => {
|
||||||
|
const layout = buildLayout(
|
||||||
|
[
|
||||||
|
node(GP, 'GP', 0),
|
||||||
|
node(P, 'P', 1),
|
||||||
|
{ ...node(A, 'A', 2), birthYear: 1900 }, // earlier birth → A is structural owner
|
||||||
|
node(R, 'R', 1),
|
||||||
|
{ ...node(B, 'B', 2), birthYear: 1910 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
parentEdge(GP, P, 'g1'),
|
||||||
|
parentEdge(P, A, 'g2'),
|
||||||
|
parentEdge(R, B, 'g3'),
|
||||||
|
spouseEdge(A, B, 'sp')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// A owns; B is absorbed into A's run → couple is exactly adjacent.
|
||||||
|
const posA = layout.positions.get(A)!;
|
||||||
|
const posB = layout.positions.get(B)!;
|
||||||
|
expect(posA.y).toBe(posB.y);
|
||||||
|
expect(Math.abs(posA.x - posB.x)).toBe(NODE_W + COL_GAP);
|
||||||
|
|
||||||
|
// R → B is cross-level: it surfaces as a distinct cross-link, and the
|
||||||
|
// geometry still lands on B's real position (carried redundantly).
|
||||||
|
expect(layout.crossLinks).toEqual([{ parentId: R, childId: B }]);
|
||||||
|
expect(layout.positions.get(B)).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user