import { act, renderHook } from "@testing-library/react" import { describe, expect, it, vi } from "vitest" import { useSortableList } from "./useSortableList" describe("useSortableList", () => { const initialItems = ["a", "b", "c", "d"] it("should initialize with items and null activeId", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) expect(result.current.items).toEqual(initialItems) expect(result.current.activeId).toBeNull() }) it("should set activeId on drag start", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) act(() => { result.current.handleDragStart({ active: { id: "b" } } as any) }) expect(result.current.activeId).toBe("b") }) it("should reorder items on drag end and reset activeId", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) act(() => { result.current.handleDragStart({ active: { id: "b" } } as any) }) act(() => { result.current.handleDragEnd({ active: { id: "b" }, over: { id: "d" } } as any) }) expect(result.current.items).toEqual(["a", "c", "d", "b"]) expect(result.current.activeId).toBeNull() }) it("should not reorder if over is null or same as active", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) act(() => { result.current.handleDragStart({ active: { id: "b" } } as any) }) act(() => { result.current.handleDragEnd({ active: { id: "b" }, over: null } as any) }) expect(result.current.items).toEqual(initialItems) act(() => { result.current.handleDragEnd({ active: { id: "b" }, over: { id: "b" } } as any) }) expect(result.current.items).toEqual(initialItems) }) it("should call onReorder and onItemsChange if provided", () => { const onReorder = vi.fn() const onItemsChange = vi.fn() const { result } = renderHook(() => useSortableList({ items: initialItems, onReorder, onItemsChange }), ) act(() => { result.current.handleDragStart({ active: { id: "a" } } as any) }) act(() => { result.current.handleDragEnd({ active: { id: "a" }, over: { id: "c" } } as any) }) expect(onReorder).toHaveBeenCalledWith(0, 2) expect(onItemsChange).toHaveBeenCalledWith(["b", "c", "a", "d"]) }) it("should reset activeId on drag cancel", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) act(() => { result.current.handleDragStart({ active: { id: "b" } } as any) }) act(() => { result.current.handleDragCancel() }) expect(result.current.activeId).toBeNull() }) it("should handle object items with id property", () => { const objectItems = [ { id: "x", label: "X" }, { id: "y", label: "Y" }, { id: "z", label: "Z" }, ] const { result } = renderHook(() => useSortableList({ items: objectItems })) act(() => { result.current.handleDragStart({ active: { id: "y" } } as any) }) act(() => { result.current.handleDragEnd({ active: { id: "y" }, over: { id: "z" } } as any) }) expect(result.current.items.map(i => (typeof i === "string" ? i : i.id))).toEqual([ "x", "z", "y", ]) }) it("should allow setItems to update items", () => { const { result } = renderHook(() => useSortableList({ items: initialItems })) act(() => { result.current.setItems(["foo", "bar"]) }) expect(result.current.items).toEqual(["foo", "bar"]) }) })