Files
oh-my-pi/packages/coding-agent/test/modes/components/settings-selector-memory-refresh.test.ts
T
can1357 a707e2daf9 feat(tui-components): added searchable filtering and focus retention for settings lists
- Added type-to-search filtering across setting labels, IDs, values, and descriptions.
- Preserved selected item focus by ID when replacing settings during an active filter.
- Displayed search status, empty-filter hints, and no-match messaging while searching.
- Updated Escape handling to clear an active query before cancelling the list.
- Applied selection and navigation to filtered items to keep behavior consistent under search.
2026-06-10 04:24:54 +02:00

103 lines
3.3 KiB
TypeScript

import { afterEach, beforeAll, beforeEach, describe, expect, it } from "bun:test";
import { resetSettingsForTest, Settings, settings } from "@oh-my-pi/pi-coding-agent/config/settings";
import { SettingsSelectorComponent } from "@oh-my-pi/pi-coding-agent/modes/components/settings-selector";
import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
beforeAll(async () => {
await initTheme();
});
beforeEach(async () => {
resetSettingsForTest();
await Settings.init({ inMemory: true });
});
afterEach(() => {
resetSettingsForTest();
});
function createSelector(onCancel: () => void = () => {}): SettingsSelectorComponent {
return new SettingsSelectorComponent(
{
availableThinkingLevels: [],
thinkingLevel: undefined,
availableThemes: ["dark"],
cwd: process.cwd(),
},
{
onChange: () => {},
onCancel,
},
);
}
/** Switch the selector to the memory tab. SETTING_TABS puts memory at index 4 (after appearance/model/interaction/context). */
function focusMemoryTab(comp: SettingsSelectorComponent): void {
for (let i = 0; i < 4; i++) {
comp.handleInput("\x1b[C");
}
}
describe("SettingsSelectorComponent memory tab", () => {
it("reveals condition-gated Hindsight rows the moment memory.backend changes via the submenu", () => {
settings.set("memory.backend", "off");
const comp = createSelector();
focusMemoryTab(comp);
const before = comp.render(120).join("\n");
expect(before).toContain("Memory Backend");
expect(before).not.toContain("Hindsight API URL");
// Memory Backend is the only visible row, so it's already selected at index 0.
// Enter opens the SelectSubmenu pre-positioned on "off"; navigate to "hindsight" (index 2) and confirm.
comp.handleInput("\n");
comp.handleInput("\x1b[B");
comp.handleInput("\x1b[B");
comp.handleInput("\n");
expect(settings.get("memory.backend")).toBe("hindsight");
const after = comp.render(120).join("\n");
expect(after).toContain("Memory Backend");
expect(after).toContain("Hindsight API URL");
expect(after).toContain("Hindsight Auto Recall");
});
it("hides Hindsight rows again when the backend is switched back to off without leaving the tab", () => {
settings.set("memory.backend", "hindsight");
const comp = createSelector();
focusMemoryTab(comp);
expect(comp.render(120).join("\n")).toContain("Hindsight API URL");
// Open Memory Backend → SelectSubmenu pre-selects the current value
// ("hindsight" at index 2) → step up twice to reach "off" → Enter confirms.
comp.handleInput("\n");
comp.handleInput("\x1b[A");
comp.handleInput("\x1b[A");
comp.handleInput("\n");
expect(settings.get("memory.backend")).toBe("off");
const after = comp.render(120).join("\n");
expect(after).toContain("Memory Backend");
expect(after).not.toContain("Hindsight API URL");
expect(after).not.toContain("Hindsight Auto Recall");
});
it("clears settings search on Escape before closing the selector", () => {
let cancelCount = 0;
const comp = createSelector(() => {
cancelCount++;
});
comp.handleInput("b");
expect(comp.render(120).join("\n")).toContain("Search: b");
comp.handleInput("\x1b");
expect(cancelCount).toBe(0);
expect(comp.render(120).join("\n")).not.toContain("Search: b");
comp.handleInput("\x1b");
expect(cancelCount).toBe(1);
});
});