diff --git a/frontend/src/lib/person/genealogy/layout/tidyTree.test.ts b/frontend/src/lib/person/genealogy/layout/tidyTree.test.ts index 18c05c3f..b68d63a4 100644 --- a/frontend/src/lib/person/genealogy/layout/tidyTree.test.ts +++ b/frontend/src/lib/person/genealogy/layout/tidyTree.test.ts @@ -10,6 +10,14 @@ function leaf(id: string, width = W): TidyNode { return { id, width, children: [] }; } +function node(id: string, children: TidyNode[], width = W): TidyNode { + return { id, width, children }; +} + +function center(x: Map, n: TidyNode): number { + return x.get(n.id)! + n.width / 2; +} + describe('tidyTree — leaf base case', () => { it('a single leaf lays out at x = 0', () => { const a = leaf('a'); @@ -17,3 +25,23 @@ describe('tidyTree — leaf base case', () => { expect(x.get('a')).toBe(0); }); }); + +describe('tidyTree — ancestor centring', () => { + it('a parent is centred over the span of its two children', () => { + const c1 = leaf('c1'); + const c2 = leaf('c2'); + const p = node('p', [c1, c2]); + const x = layoutForest([p], GAP); + + const pc = center(x, p); + const lo = center(x, c1); + const hi = center(x, c2); + // Parent sits exactly at the midpoint of its children's centres … + expect(pc).toBe((lo + hi) / 2); + // … which is within their span (the named-bug guard generalises this). + expect(pc).toBeGreaterThanOrEqual(Math.min(lo, hi)); + expect(pc).toBeLessThanOrEqual(Math.max(lo, hi)); + // Children do not overlap. + expect(Math.abs(x.get('c2')! - x.get('c1')!)).toBeGreaterThanOrEqual(W + GAP); + }); +});