import { act, renderHook } from "@testing-library/react"; import assert from "node:assert/strict"; import { afterEach, describe, it, mock, } from "node:test"; import { useIO } from "./useIO"; import { useListeners } from "./useListeners"; import { useRefs } from "./useRefs"; import { EventBus } from "../../plugins/eventBus"; describe("React utility hook lifecycle", () => { const originalIntersectionObserver = globalThis.IntersectionObserver; afterEach(() => { globalThis.IntersectionObserver = originalIntersectionObserver; }); it("keeps refs stable while length is unchanged", () => { const { result, rerender } = renderHook(({ length }) => useRefs(length), { initialProps: { length: 2 }, }); const firstRefs = result.current; rerender({ length: 2 }); assert.strictEqual(result.current[0], firstRefs[0]); assert.strictEqual(result.current[1], firstRefs[1]); }); it("disconnects IntersectionObserver on unmount", () => { const disconnect = mock.fn(); class IntersectionObserverMock { disconnect = disconnect; observe() {} takeRecords() { return []; } unobserve() {} root = null; rootMargin = "0px"; scrollMargin = "0px"; thresholds = [ 0 ]; } globalThis.IntersectionObserver = IntersectionObserverMock as typeof IntersectionObserver; const ref = { current: document.createElement("div") }; const { unmount } = renderHook(() => useIO({ ref, callback: mock.fn() })); unmount(); assert.strictEqual(disconnect.mock.calls.length, 1); }); it("replaces event callbacks after rerender", () => { const eventBus = new EventBus(); const target = document.createElement("div"); const ref = { current: target }; const first = mock.fn(); const second = mock.fn(); const { rerender } = renderHook(({ listener }) => useListeners({ EventBusInstance: eventBus, listeners: { change: listener }, ref, }), { initialProps: { listener: first } }); act(() => target.dispatchEvent(new window.Event("change"))); rerender({ listener: second }); act(() => target.dispatchEvent(new window.Event("change"))); assert.strictEqual(first.mock.calls.length, 1); assert.strictEqual(second.mock.calls.length, 1); }); });