aaaa bbbb cccc dddd eeee ffff
'; +const ONE_LINE = 'short
'; + +test("swapping children re-measures without a resize", async () => { + const el = mount(TWO_LINES); + expect(bars(el)).toHaveLength(2); + await settle(); + el.replaceChildren(fragment(ONE_LINE)); + await expect.poll(() => bars(el).length).toBe(1); + expect(el.hasAttribute("data-bones-measured")).toBe(true); +}); + +test("editing text re-measures", async () => { + const el = mount(TWO_LINES); + expect(bars(el)).toHaveLength(2); + await settle(); + (el.querySelector("p")!.firstChild as Text).data = "short"; + await expect.poll(() => bars(el).length).toBe(1); +}); + +test("an emptied subtree deactivates to the CSS path", async () => { + const el = mount(TWO_LINES); + await settle(); + el.replaceChildren(); + await expect.poll(() => el.hasAttribute("data-bones-measured")).toBe(false); + expect(bars(el)).toHaveLength(0); +}); + +test("bar rendering does not observe itself", async () => { + // Bars render into the shadow root; an observer on the host's light tree + // never reports them. If it did, this would loop: each re-measure replaces + // the bar elements, which would re-trigger the observer forever. + const el = mount(TWO_LINES); + await settle(); + el.replaceChildren(fragment(ONE_LINE)); + await expect.poll(() => bars(el).length).toBe(1); + const bar = bars(el)[0]; + await settle(); + expect(bars(el)[0]).toBe(bar); +}); + +test("a class change does not re-measure", async () => { + // Attribute mutations are deliberately excluded from the observer config: + // a class or style tick anywhere in the boundary must not touch the bars. + const el = mount(TWO_LINES); + await settle(); + const bar = bars(el)[0]; + el.querySelector("p")!.className = "x"; + await settle(); + expect(bars(el)).toHaveLength(2); + expect(bars(el)[0]).toBe(bar); +});