/* Copyright 2026 Marimo. All rights reserved. */
import { fireEvent, render, screen } from "@testing-library/react";
import { beforeEach, describe, expect, it, type Mock, vi } from "vitest";
import { TooltipProvider } from "@/components/ui/tooltip";
import { useInputHistory } from "@/hooks/useInputHistory";
import { Debugger } from "../debugger-code";
// Mock CodeMirror language extensions
vi.mock("@uiw/codemirror-extensions-langs", () => ({
langs: {
sh: () => [],
py: () => [],
},
}));
// Mock useInputHistory hook
vi.mock("@/hooks/useInputHistory");
const renderWithProvider = (ui: React.ReactElement) => {
return render({ui});
};
// Default mock implementation
const mockNavigateUp = vi.fn();
const mockNavigateDown = vi.fn();
const mockAddToHistory = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
(useInputHistory as Mock).mockReturnValue({
history: [],
navigateUp: mockNavigateUp,
navigateDown: mockNavigateDown,
addToHistory: mockAddToHistory,
});
});
describe("Debugger", () => {
it("should render debugger output and controls", () => {
const onSubmit = vi.fn();
renderWithProvider();
// Check that control buttons are rendered
expect(screen.getByTestId("debugger-next-button")).toBeInTheDocument();
expect(screen.getByTestId("debugger-continue-button")).toBeInTheDocument();
expect(screen.getByTestId("debugger-stack-button")).toBeInTheDocument();
expect(screen.getByTestId("debugger-help-button")).toBeInTheDocument();
});
it("should call onSubmit with 'n' when next button is clicked", () => {
const onSubmit = vi.fn();
renderWithProvider();
fireEvent.click(screen.getByTestId("debugger-next-button"));
expect(onSubmit).toHaveBeenCalledWith("n");
});
it("should call onSubmit with 'c' when continue button is clicked", () => {
const onSubmit = vi.fn();
renderWithProvider();
fireEvent.click(screen.getByTestId("debugger-continue-button"));
expect(onSubmit).toHaveBeenCalledWith("c");
});
it("should call onSubmit with 'bt' when stack button is clicked", () => {
const onSubmit = vi.fn();
renderWithProvider();
fireEvent.click(screen.getByTestId("debugger-stack-button"));
expect(onSubmit).toHaveBeenCalledWith("bt");
});
it("should call onSubmit with 'help' when help button is clicked", () => {
const onSubmit = vi.fn();
renderWithProvider();
fireEvent.click(screen.getByTestId("debugger-help-button"));
expect(onSubmit).toHaveBeenCalledWith("help");
});
});
describe("Debugger command history integration", () => {
it("should initialize useInputHistory hook with correct props", () => {
const onSubmit = vi.fn();
renderWithProvider();
expect(useInputHistory).toHaveBeenCalled();
const calls = (useInputHistory as Mock).mock.calls;
expect(calls.length).toBeGreaterThan(0);
// Verify hook is called with value and setValue
const lastCall = calls[calls.length - 1][0];
expect(lastCall).toHaveProperty("value");
expect(lastCall).toHaveProperty("setValue");
expect(typeof lastCall.setValue).toBe("function");
});
it("should call navigateUp when ArrowUp is pressed in input area", () => {
const onSubmit = vi.fn();
const { container } = renderWithProvider(
,
);
// Find the debugger input wrapper div (parent of CodeMirror)
const inputWrapper =
container.querySelector(".debugger-input")?.parentElement;
expect(inputWrapper).toBeTruthy();
fireEvent.keyDown(inputWrapper!, { key: "ArrowUp" });
expect(mockNavigateUp).toHaveBeenCalled();
});
it("should call navigateDown when ArrowDown is pressed in input area", () => {
const onSubmit = vi.fn();
const { container } = renderWithProvider(
,
);
// Find the debugger input wrapper div (parent of CodeMirror)
const inputWrapper =
container.querySelector(".debugger-input")?.parentElement;
expect(inputWrapper).toBeTruthy();
fireEvent.keyDown(inputWrapper!, { key: "ArrowDown" });
expect(mockNavigateDown).toHaveBeenCalled();
});
it("should not call navigation functions for other keys", () => {
const onSubmit = vi.fn();
const { container } = renderWithProvider(
,
);
const inputWrapper =
container.querySelector(".debugger-input")?.parentElement;
expect(inputWrapper).toBeTruthy();
fireEvent.keyDown(inputWrapper!, { key: "ArrowLeft" });
fireEvent.keyDown(inputWrapper!, { key: "ArrowRight" });
fireEvent.keyDown(inputWrapper!, { key: "a" });
expect(mockNavigateUp).not.toHaveBeenCalled();
expect(mockNavigateDown).not.toHaveBeenCalled();
});
});