108 lines
2.9 KiB
TypeScript
108 lines
2.9 KiB
TypeScript
import { afterEach, beforeAll, describe, expect, it, vi } from "bun:test";
|
|
|
|
import { HookInputComponent } from "@oh-my-pi/pi-coding-agent/modes/components/hook-input";
|
|
import { getThemeByName, setThemeInstance } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
import type { TUI } from "@oh-my-pi/pi-tui";
|
|
|
|
beforeAll(async () => {
|
|
const theme = await getThemeByName("dark");
|
|
if (!theme) {
|
|
throw new Error("Failed to load dark theme for tests");
|
|
}
|
|
setThemeInstance(theme);
|
|
});
|
|
describe("HookInputComponent timeout", () => {
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("resets timeout on user activity and still expires when idle", () => {
|
|
vi.useFakeTimers();
|
|
|
|
const onSubmit = vi.fn();
|
|
const onCancel = vi.fn();
|
|
const onTimeout = vi.fn();
|
|
const tui = { requestRender: vi.fn() } as unknown as TUI;
|
|
|
|
const component = new HookInputComponent("Prompt", undefined, onSubmit, onCancel, {
|
|
timeout: 1_000,
|
|
tui,
|
|
onTimeout,
|
|
});
|
|
|
|
vi.advanceTimersByTime(900);
|
|
component.handleInput("a");
|
|
|
|
vi.advanceTimersByTime(900);
|
|
component.handleInput("\x7f");
|
|
|
|
vi.advanceTimersByTime(900);
|
|
expect(onTimeout).not.toHaveBeenCalled();
|
|
expect(onCancel).not.toHaveBeenCalled();
|
|
|
|
vi.advanceTimersByTime(200);
|
|
expect(onTimeout).toHaveBeenCalledTimes(1);
|
|
expect(onCancel).toHaveBeenCalledTimes(1);
|
|
|
|
component.dispose();
|
|
});
|
|
|
|
it("preserves submit behavior", () => {
|
|
vi.useFakeTimers();
|
|
|
|
const onSubmit = vi.fn();
|
|
const onCancel = vi.fn();
|
|
const onTimeout = vi.fn();
|
|
const tui = { requestRender: vi.fn() } as unknown as TUI;
|
|
|
|
const component = new HookInputComponent("Prompt", undefined, onSubmit, onCancel, {
|
|
timeout: 1_000,
|
|
tui,
|
|
onTimeout,
|
|
});
|
|
|
|
component.handleInput("h");
|
|
component.handleInput("i");
|
|
component.handleInput("\n");
|
|
|
|
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
expect(onSubmit).toHaveBeenCalledWith("hi");
|
|
expect(onCancel).not.toHaveBeenCalled();
|
|
expect(onTimeout).not.toHaveBeenCalled();
|
|
|
|
component.dispose();
|
|
});
|
|
|
|
it("absorbs enhanced-paste payloads via pasteText and resets the timeout", () => {
|
|
// Regression: enhanced-paste (kitty OSC 5522) focus routing only targets
|
|
// components exposing a `pasteText` hook; without one the payload landed
|
|
// in the hidden main prompt behind the dialog (#2127 contract).
|
|
vi.useFakeTimers();
|
|
|
|
const onSubmit = vi.fn();
|
|
const onCancel = vi.fn();
|
|
const onTimeout = vi.fn();
|
|
const tui = { requestRender: vi.fn() } as unknown as TUI;
|
|
|
|
const component = new HookInputComponent("Prompt", undefined, onSubmit, onCancel, {
|
|
timeout: 1_000,
|
|
tui,
|
|
onTimeout,
|
|
});
|
|
|
|
vi.advanceTimersByTime(900);
|
|
component.pasteText("sk-line1\nsk-line2");
|
|
|
|
vi.advanceTimersByTime(900);
|
|
expect(onTimeout).not.toHaveBeenCalled();
|
|
expect(onCancel).not.toHaveBeenCalled();
|
|
|
|
component.handleInput("\n");
|
|
|
|
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
expect(onSubmit).toHaveBeenCalledWith("sk-line1sk-line2");
|
|
|
|
component.dispose();
|
|
});
|
|
});
|