Files
oh-my-pi/packages/coding-agent/test/modes/components/session-selector-scope.test.ts
T
can1357 24c8bb24c6 feat(session): added modular session APIs and rebuilt listing/persistence behavior
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
2026-06-14 02:02:53 +02:00

108 lines
3.2 KiB
TypeScript

import { beforeAll, describe, expect, it } from "bun:test";
import { SessionSelectorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/session-selector";
import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
import type { SessionInfo } from "@oh-my-pi/pi-coding-agent/session/session-listing";
beforeAll(() => {
initTheme();
});
function createSession(id: string, title: string, cwd: string): SessionInfo {
return {
path: `${cwd}/${id}.jsonl`,
id,
cwd,
title,
created: new Date("2024-01-01T00:00:00Z"),
modified: new Date("2024-01-02T00:00:00Z"),
messageCount: 1,
size: 0,
firstMessage: `${title} first message`,
allMessagesText: `${title} first message`,
};
}
const TAB = "\t";
describe("SessionSelectorComponent scope toggle", () => {
it("loads the all-projects list on Tab and surfaces each session's directory", async () => {
const folder = [createSession("local", "Local", "/work/current")];
const global = [
createSession("local", "Local", "/work/current"),
createSession("remote", "Remote", "/work/other-project"),
];
let loads = 0;
const selector = new SessionSelectorComponent(
folder,
() => {},
() => {},
() => {},
{
loadAllSessions: async () => {
loads++;
return global;
},
},
);
// Folder scope: header says current folder, no foreign cwd column.
expect(selector.render(120).join("\n")).toContain("(current folder)");
expect(selector.render(120).join("\n")).not.toContain("other-project");
selector.handleInput(TAB);
await Bun.sleep(0);
const rendered = selector.render(120).join("\n");
expect(rendered).toContain("(all projects)");
expect(rendered).toContain("other-project");
expect(loads).toBe(1);
// Toggling back returns to folder scope without reloading.
selector.handleInput(TAB);
await Bun.sleep(0);
expect(selector.render(120).join("\n")).toContain("(current folder)");
expect(loads).toBe(1);
// Re-entering all scope reuses the cached global list.
selector.handleInput(TAB);
await Bun.sleep(0);
expect(loads).toBe(1);
});
it("returns the full selected session, including its cwd", async () => {
const folder = [createSession("local", "Local", "/work/current")];
const remote = createSession("remote", "Remote", "/work/other-project");
const selected: SessionInfo[] = [];
const selector = new SessionSelectorComponent(
folder,
session => selected.push(session),
() => {},
() => {},
{ loadAllSessions: async () => [remote] },
);
selector.handleInput(TAB);
await Bun.sleep(0);
selector.handleInput("\n");
expect(selected).toHaveLength(1);
expect(selected[0]?.path).toBe(remote.path);
expect(selected[0]?.cwd).toBe("/work/other-project");
});
it("opens directly in all-projects scope when started there with a preloaded list", () => {
const global = [createSession("remote", "Remote", "/work/other-project")];
const selector = new SessionSelectorComponent(
[],
() => {},
() => {},
() => {},
{ allSessions: global, startInAllScope: true, loadAllSessions: async () => global },
);
const rendered = selector.render(120).join("\n");
expect(rendered).toContain("(all projects)");
expect(rendered).toContain("other-project");
});
});