// @vitest-environment jsdom import { act, renderHook } from "@testing-library/react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { useMountTransition } from "./useMountTransition"; beforeEach(() => { vi.useFakeTimers(); // 让 rAF 同步执行,便于断言 isVisible 翻转。 vi.stubGlobal("requestAnimationFrame", (cb: FrameRequestCallback) => { cb(0); return 1; }); vi.stubGlobal("cancelAnimationFrame", () => {}); }); afterEach(() => { vi.useRealTimers(); vi.unstubAllGlobals(); }); describe("useMountTransition", () => { it("renders nothing while closed", () => { const { result } = renderHook(() => useMountTransition(false, 180)); expect(result.current.shouldRender).toBe(false); expect(result.current.isVisible).toBe(false); }); it("mounts and becomes visible when opened", () => { const { result, rerender } = renderHook( ({ open }) => useMountTransition(open, 180), { initialProps: { open: false } }, ); act(() => rerender({ open: true })); expect(result.current.shouldRender).toBe(true); expect(result.current.isVisible).toBe(true); }); it("keeps rendering during exit, then unmounts after the duration", () => { const { result, rerender } = renderHook( ({ open }) => useMountTransition(open, 180), { initialProps: { open: true } }, ); act(() => rerender({ open: false })); expect(result.current.isVisible).toBe(false); expect(result.current.shouldRender).toBe(true); act(() => { vi.advanceTimersByTime(180); }); expect(result.current.shouldRender).toBe(false); }); });