/// import React from "react"; import { Collapse } from "./index"; import { act, render, screen } from "@testing-library/react"; describe("Collapse", () => { let resizeCallback: (() => void) | null = null; beforeEach(() => { resizeCallback = null; // Mock scrollHeight since jsdom doesn't compute layout Object.defineProperty(HTMLDivElement.prototype, "scrollHeight", { configurable: true, get() { return 200; }, }); // Mock ResizeObserver to capture the callback global.ResizeObserver = jest.fn().mockImplementation(callback => ({ observe: jest.fn(() => { resizeCallback = callback; }), unobserve: jest.fn(), disconnect: jest.fn(), })); }); describe("rendering", () => { it("renders children content", () => { render(

Collapsed Content

); expect(screen.getByText("Collapsed Content")).toBeInTheDocument(); }); it("renders children even when closed", () => { render(

Hidden Content

); // Content is in DOM but visually hidden via maxHeight/opacity expect(screen.getByText("Hidden Content")).toBeInTheDocument(); }); it("applies displayName correctly", () => { expect(Collapse.displayName).toBe("Collapse"); }); }); describe("open state", () => { it("sets maxHeight to scrollHeight when open", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("200px"); }); it("sets maxHeight to 0 when closed", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("0"); }); it("sets opacity to 1 when open", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.opacity).toBe("1"); }); it("sets opacity to 0 when closed", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.opacity).toBe("0"); }); }); describe("accessibility", () => { it("sets aria-hidden to false when open", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper).toHaveAttribute("aria-hidden", "false"); }); it("sets aria-hidden to true when closed", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper).toHaveAttribute("aria-hidden", "true"); }); }); describe("transition classes", () => { it("applies transition classes to the outer wrapper", () => { const { container } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper).toHaveClass("overflow-hidden"); expect(wrapper).toHaveClass("transition-all"); expect(wrapper).toHaveClass("duration-300"); expect(wrapper).toHaveClass("ease-in-out"); }); }); describe("toggling open/closed", () => { it("updates maxHeight when open prop changes to true", () => { const { container, rerender } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("0"); rerender(

Content

); expect(wrapper.style.maxHeight).toBe("200px"); }); it("updates maxHeight when open prop changes to false", () => { const { container, rerender } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("200px"); rerender(

Content

); expect(wrapper.style.maxHeight).toBe("0"); }); it("updates opacity when toggling", () => { const { container, rerender } = render(

Content

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.opacity).toBe("0"); rerender(

Content

); expect(wrapper.style.opacity).toBe("1"); }); }); describe("ResizeObserver", () => { it("creates ResizeObserver when open", () => { render(

Content

); expect(global.ResizeObserver).toHaveBeenCalled(); }); it("does not create ResizeObserver when closed", () => { render(

Content

); // ResizeObserver constructor is called but observe is not invoked // when closed, no observer is created const instances = (global.ResizeObserver as jest.Mock).mock.results; if (instances.length > 0) { const observeMock = instances[0].value.observe; expect(observeMock).not.toHaveBeenCalled(); } }); it("disconnects ResizeObserver on unmount", () => { const { unmount } = render(

Content

); const instances = (global.ResizeObserver as jest.Mock).mock.results; const disconnectMock = instances[instances.length - 1].value.disconnect; unmount(); expect(disconnectMock).toHaveBeenCalled(); }); it("invokes updateHeight via ResizeObserver callback", () => { const { container } = render(

Content

); // Change scrollHeight to simulate resize Object.defineProperty(HTMLDivElement.prototype, "scrollHeight", { configurable: true, get() { return 500; }, }); // Trigger the ResizeObserver callback within act act(() => { if (resizeCallback) { resizeCallback(); } }); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("500px"); }); }); describe("dynamic children", () => { it("re-evaluates height when children change", () => { const { rerender, container } = render(

Short

); Object.defineProperty(HTMLDivElement.prototype, "scrollHeight", { configurable: true, get() { return 400; }, }); rerender(

Short

More content that makes it taller

); const wrapper = container.firstChild as HTMLElement; expect(wrapper.style.maxHeight).toBe("400px"); }); }); });