import { beforeAll, describe, expect, it, vi } from "vitest"; import type { SessionInfo } from "../src/core/session-manager.js"; import { SessionSelectorComponent } from "../src/modes/interactive/components/session-selector.js"; import { initTheme } from "../src/modes/interactive/theme/theme.js"; async function flushPromises(): Promise { await new Promise((resolve) => { setImmediate(resolve); }); } function makeSession(overrides: Partial & { id: string }): SessionInfo { return { path: overrides.path ?? `/tmp/${overrides.id}.jsonl`, id: overrides.id, cwd: overrides.cwd ?? "", name: overrides.name, created: overrides.created ?? new Date(0), modified: overrides.modified ?? new Date(0), messageCount: overrides.messageCount ?? 1, firstMessage: overrides.firstMessage ?? "hello", allMessagesText: overrides.allMessagesText ?? "hello", }; } // Kitty keyboard protocol encoding for Ctrl+R const CTRL_R = "\x1b[114;5u"; describe("session selector rename", () => { beforeAll(() => { initTheme("dark"); }); it("shows rename hint in interactive /resume picker configuration", async () => { const sessions = [makeSession({ id: "a" })]; const selector = new SessionSelectorComponent( async () => sessions, async () => [], () => {}, () => {}, () => {}, () => {}, { showRenameHint: true }, ); await flushPromises(); const output = selector.render(120).join("\n"); expect(output).toContain("ctrl+r"); expect(output).toContain("rename"); }); it("does not show rename hint in --resume picker configuration", async () => { const sessions = [makeSession({ id: "a" })]; const selector = new SessionSelectorComponent( async () => sessions, async () => [], () => {}, () => {}, () => {}, () => {}, { showRenameHint: false }, ); await flushPromises(); const output = selector.render(120).join("\n"); expect(output).not.toContain("ctrl+r"); expect(output).not.toContain("rename"); }); it("enters rename mode on Ctrl+R and submits with Enter", async () => { const sessions = [makeSession({ id: "a", name: "Old" })]; const renameSession = vi.fn(async () => {}); const selector = new SessionSelectorComponent( async () => sessions, async () => [], () => {}, () => {}, () => {}, () => {}, { renameSession, showRenameHint: true }, ); await flushPromises(); selector.getSessionList().handleInput(CTRL_R); await flushPromises(); // Rename mode layout const output = selector.render(120).join("\n"); expect(output).toContain("Rename Session"); expect(output).not.toContain("Resume Session"); // Type and submit selector.handleInput("X"); selector.handleInput("\r"); await flushPromises(); expect(renameSession).toHaveBeenCalledTimes(1); expect(renameSession).toHaveBeenCalledWith(sessions[0]!.path, "XOld"); }); });