import { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { SiteOutlineController } from "@/client/sites/islands/site-outline-controller"; let host: HTMLElement; let root: Root; beforeEach(() => { vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true); vi.useFakeTimers(); vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => { return window.setTimeout(() => cb(performance.now()), 0) as unknown as number; }); vi.spyOn(window, "cancelAnimationFrame").mockImplementation((id) => { window.clearTimeout(id); }); document.body.innerHTML = `

Intro

Second

`; const intro = document.getElementById("intro")!; const second = document.getElementById("second")!; Object.defineProperty(intro, "offsetParent", { configurable: true, get: () => document.body }); Object.defineProperty(second, "offsetParent", { configurable: true, get: () => document.body }); intro.getBoundingClientRect = () => ({ top: 40, bottom: 80 }) as DOMRect; second.getBoundingClientRect = () => ({ top: 520, bottom: 560 }) as DOMRect; host = document.getElementById("rail-host")!; root = createRoot(host); act(() => { root.render( , ); }); }); afterEach(() => { act(() => { root.unmount(); }); document.body.innerHTML = ""; vi.useRealTimers(); vi.restoreAllMocks(); vi.unstubAllGlobals(); }); describe("SiteOutlineController", () => { it("updates every duplicate outline link on simulated viewport changes", () => { expect(document.querySelectorAll("[data-outline-id='intro'][data-active='true']").length).toBeGreaterThanOrEqual(2); expect( document.querySelectorAll("[data-outline-id='intro'][aria-current='location']").length, ).toBeGreaterThanOrEqual(2); const intro = document.getElementById("intro")!; const second = document.getElementById("second")!; intro.getBoundingClientRect = () => ({ top: -140, bottom: -80 }) as DOMRect; second.getBoundingClientRect = () => ({ top: 180, bottom: 220 }) as DOMRect; act(() => { window.dispatchEvent(new Event("scroll")); vi.runOnlyPendingTimers(); }); expect(document.querySelectorAll("[data-outline-id='second'][data-active='true']").length).toBeGreaterThanOrEqual( 2, ); expect(document.querySelectorAll("[data-outline-id='intro'][aria-current='location']")).toHaveLength(0); }); });