/* Copyright 2026 Marimo. All rights reserved. */
import { act, render, renderHook } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { useResizeHandle } from "../useResizeHandle";
describe("useResizeHandle", () => {
it("should initialize with correct refs and style", () => {
const { result } = renderHook(() =>
useResizeHandle({
startingWidth: 500,
onResize: vi.fn(),
}),
);
expect(result.current.resizableDivRef.current).toBeNull();
expect(result.current.handleRefs.left.current).toBeNull();
expect(result.current.handleRefs.right.current).toBeNull();
expect(result.current.style).toEqual({ width: "500px" });
});
it("should handle contentWidth starting width", () => {
const { result } = renderHook(() =>
useResizeHandle({
startingWidth: "contentWidth",
onResize: vi.fn(),
}),
);
// Defaults to medium width
expect(result.current.style).toEqual({
width: "var(--content-width-medium)",
});
});
it("should call onResize when resizing", () => {
const onResize = vi.fn();
// Create a test component that uses the hook
const TestComponent = () => {
const { resizableDivRef, handleRefs } = useResizeHandle({
startingWidth: 500,
onResize,
});
return (
);
};
const { getByTestId } = render();
const resizableDiv = getByTestId("resizable-div") as HTMLDivElement;
const rightHandle = getByTestId("right-handle") as HTMLDivElement;
// Simulate resize
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
rightHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: 100 });
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("600px"); // 500px + 100px movement
expect(onResize).toHaveBeenCalledWith(600);
// Resize left handle
const leftHandle = getByTestId("left-handle") as HTMLDivElement;
// Simulate resize
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
leftHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: -100 });
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("700px"); // 600px - (-100px) movement
expect(onResize).toHaveBeenCalledWith(700);
});
it("should handle resizing with only left handle", () => {
const onResize = vi.fn();
// Create a test component that uses the hook
const TestComponent = () => {
const { resizableDivRef, handleRefs } = useResizeHandle({
startingWidth: 500,
onResize,
});
return (
);
};
const { getByTestId } = render();
const resizableDiv = getByTestId("resizable-div") as HTMLDivElement;
const leftHandle = getByTestId("left-handle") as HTMLDivElement;
// Simulate resize
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
leftHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: -100 });
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("600px"); // 500px - (-100px) movement
expect(onResize).toHaveBeenCalledWith(600);
});
it("should handle resizing with only right handle", () => {
const onResize = vi.fn();
// Create a test component that uses the hook
const TestComponent = () => {
const { resizableDivRef, handleRefs } = useResizeHandle({
startingWidth: 500,
onResize,
});
return (
);
};
const { getByTestId } = render();
const resizableDiv = getByTestId("resizable-div") as HTMLDivElement;
const rightHandle = getByTestId("right-handle") as HTMLDivElement;
// Simulate resize
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
rightHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: 100 });
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("600px"); // 500px + 100px movement
expect(onResize).toHaveBeenCalledWith(600);
});
it("should handle min and max width", () => {
const onResize = vi.fn();
// Create a test component that uses the hook
const TestComponent = () => {
const { resizableDivRef, handleRefs } = useResizeHandle({
startingWidth: 500,
minWidth: 400,
maxWidth: 600,
onResize,
});
return (
);
};
const { getByTestId } = render();
const resizableDiv = getByTestId("resizable-div") as HTMLDivElement;
const rightHandle = getByTestId("right-handle") as HTMLDivElement;
// Test min width
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
rightHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: -200 }); // Try to resize below min
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("400px"); // Should be clamped to min width
expect(onResize).toHaveBeenCalledWith(400);
// Test max width
act(() => {
const mousedownEvent = new MouseEvent("mousedown", { clientX: 0 });
rightHandle.dispatchEvent(mousedownEvent);
const mousemoveEvent = new MouseEvent("mousemove", { clientX: 200 }); // Try to resize above max
document.dispatchEvent(mousemoveEvent);
const mouseupEvent = new MouseEvent("mouseup");
document.dispatchEvent(mouseupEvent);
});
expect(resizableDiv.style.width).toBe("600px"); // Should be clamped to max width
expect(onResize).toHaveBeenCalledWith(600);
});
});