clanker-agent/packages/coding-agent/test/session-selector-rename.test.ts
Harivansh Rathi 0250f72976 move pi-mono into companion-cloud as apps/companion-os
- Copy all pi-mono source into apps/companion-os/
- Update Dockerfile to COPY pre-built binary instead of downloading from GitHub Releases
- Update deploy-staging.yml to build pi from source (bun compile) before Docker build
- Add apps/companion-os/** to path triggers
- No more cross-repo dispatch needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:22:50 -08:00

103 lines
3 KiB
TypeScript

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<void> {
await new Promise<void>((resolve) => {
setImmediate(resolve);
});
}
function makeSession(
overrides: Partial<SessionInfo> & { 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");
});
});