import { test, expect } from "bun:test"; import { Window } from "happy-dom"; import { REACTIVE_RUNTIME } from "../src/reactive-runtime.ts"; function fixture(panel: Record, clipped = false) { const win = new Window(); win.document.body.innerHTML = '
'; const element = win.document.querySelector('[data-wrn-anchored]')! as any; const host = element.parentElement; const rect = (left: number, top: number, width: number, height: number) => ({left, top, width, height, right:left+width, bottom:top+height}); host.getBoundingClientRect = () => rect(270, 170, 40, 30); element.getBoundingClientRect = () => rect(panel.left, panel.top, Math.min(panel.width, parseFloat(element.style.maxWidth) || Infinity), Math.min(panel.height, parseFloat(element.style.maxHeight) || Infinity)); if (clipped) { const clip = win.document.querySelector('#clip')! as any; clip.style.overflow = 'hidden'; clip.getBoundingClientRect = () => rect(100, 50, 220, 220); Object.defineProperty(clip, 'clientWidth', {value:220}); Object.defineProperty(clip, 'clientHeight', {value:220}); } const start = REACTIVE_RUNTIME.indexOf(' function isRenderedElement('); const end = REACTIVE_RUNTIME.indexOf(' function repositionAnchored(', start); const clamp = new Function('window', 'document', 'ANCHOR_MARGIN', REACTIVE_RUNTIME.slice(start,end) + '; return clampAnchored;')(win, win.document, 8); return {win, element, clamp}; } test('anchored panels fit clipping containers and positioning does not drift', async () => { const {win, element, clamp} = fixture({left:40,top:208,width:180,height:100}, true); clamp(element); expect(element.style.translate).toBe('68px -146px'); clamp(element); expect(element.style.translate).toBe('68px -146px'); await win.happyDOM.close(); }); test('oversized panels become scrollable and recover authored sizing when space returns', async () => { const {win, element, clamp} = fixture({left:40,top:60,width:500,height:400}, true); element.style.minWidth = '300px'; clamp(element); expect(element.style.maxWidth).toBe('204px'); expect(element.style.maxHeight).toBe('204px'); expect(element.style.overflow).toBe('auto'); element.parentElement.parentElement.style.overflow = 'visible'; clamp(element); expect(element.style.minWidth).toBe('300px'); expect(element.style.maxWidth).toBe(''); await win.happyDOM.close(); });