diff --git a/frontend/src/routes/stammbaum/page.svelte.test.ts b/frontend/src/routes/stammbaum/page.svelte.test.ts index 578aff76..baa1450f 100644 --- a/frontend/src/routes/stammbaum/page.svelte.test.ts +++ b/frontend/src/routes/stammbaum/page.svelte.test.ts @@ -157,6 +157,15 @@ describe('stammbaum page', () => { // desktop side panel is a flex sibling that never overlaps the canvas, so no // centring should fire there. These tests prove the matchMedia gate around // selectPerson, not just the recentreAbove geometry (covered in panZoom.test). + // We assert on the rendered viewBox — a pure function of the view state — so a + // recentre is observed as a shifted origin, with no dependence on the noisy + // mount-time URL-mirror timing. + function svgViewBox(): string { + const svg = document.querySelector('svg[aria-label="Stammbaum"]'); + if (!svg) throw new Error('No Stammbaum svg rendered'); + return svg.getAttribute('viewBox') ?? ''; + } + it('recentres the tapped person when matchMedia reports mobile (#703 AC8)', async () => { mockMatchMedia(true); mockPage.url = new URL('http://localhost/stammbaum'); @@ -164,15 +173,17 @@ describe('stammbaum page', () => { render(Stammbaum, { props: { data: { nodes: familyNodes, edges: [], initialView: DEFAULT_VIEW } } }); - // Let the mount-time URL mirror settle, then isolate the tap's effect. - await vi.waitFor(() => expect(replaceState).toHaveBeenCalled()); - replaceState.mockClear(); + const before = await vi.waitFor(() => { + const vb = svgViewBox(); + expect(vb).toBeTruthy(); + return vb; + }); await page.getByRole('button', { name: 'Anna Schmidt' }).click(); - // The mobile tap recentres the canvas → the view changes → the ?cx&cy&z - // mirror effect re-fires. (Desktop, below, leaves the view untouched.) - await vi.waitFor(() => expect(replaceState).toHaveBeenCalled()); + // The mobile tap recentres the canvas, lifting the anchor above the sheet, + // so the viewBox origin shifts. + await vi.waitFor(() => expect(svgViewBox()).not.toBe(before)); }); it('does not recentre on tap when matchMedia reports desktop (#703 AC8)', async () => { @@ -182,14 +193,17 @@ describe('stammbaum page', () => { render(Stammbaum, { props: { data: { nodes: familyNodes, edges: [], initialView: DEFAULT_VIEW } } }); - await vi.waitFor(() => expect(replaceState).toHaveBeenCalled()); - replaceState.mockClear(); + const before = await vi.waitFor(() => { + const vb = svgViewBox(); + expect(vb).toBeTruthy(); + return vb; + }); await page.getByRole('button', { name: 'Anna Schmidt' }).click(); // The tap registers — the desktop side panel opens — but no recentre fires, - // so the view never changes and the mirror effect stays silent. + // so the viewBox is unchanged. await expect.element(page.getByRole('complementary')).toBeVisible(); - expect(replaceState).not.toHaveBeenCalled(); + expect(svgViewBox()).toBe(before); }); });