import { setKeybindings } from "@earendil-works/pi-tui"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { KeybindingsManager } from "../src/core/keybindings.ts"; import { ScopedModelsSelectorComponent } from "../src/modes/interactive/components/scoped-models-selector.ts"; import { initTheme } from "../src/modes/interactive/theme/theme.ts"; import { stripAnsi } from "../src/utils/ansi.ts"; import { createHarness, type Harness } from "./suite/harness.ts"; interface ModelState { id: string; name: string; enabled: boolean; } function getMarkerStates(selector: ScopedModelsSelectorComponent, models: ModelState[]): boolean[] { const lines = stripAnsi(selector.render(120).join("\n")).split("\n"); return models.map((model) => { const line = lines.find((candidate) => candidate.includes(`${model.id} [`)); if (!line) throw new Error(`Expected rendered row for ${model.id}`); return line.slice(2).startsWith("✓ "); }); } describe("scoped models selector", () => { let harness: Harness | undefined; beforeAll(() => { initTheme("dark"); }); beforeEach(() => { setKeybindings(new KeybindingsManager()); }); afterEach(() => { harness?.cleanup(); harness = undefined; }); async function createSelector(models: ModelState[]) { harness = await createHarness({ models }); const provider = harness.models[0].provider; const selector = new ScopedModelsSelectorComponent( { allModels: [...harness.models], enabledModelIds: models.filter((model) => model.enabled).map((model) => `${provider}/${model.id}`), }, { onChange: (enabledModelIds) => { for (const model of models) { model.enabled = enabledModelIds === null || enabledModelIds.includes(`${provider}/${model.id}`); } }, onPersist: () => {}, onCancel: () => {}, }, ); return selector; } it("marks every model after enabling all", async () => { const models = [ { id: "model-a", name: "Model A", enabled: true }, { id: "model-b", name: "Model B", enabled: false }, { id: "model-c", name: "Model C", enabled: false }, ]; const selector = await createSelector(models); selector.handleInput("\x01"); expect(models.map((model) => model.enabled)).toEqual([true, true, true]); expect(getMarkerStates(selector, models)).toEqual([true, true, true]); expect(stripAnsi(selector.render(120).join("\n"))).toContain("all enabled"); }); it("disables only the selected model after enabling all", async () => { const models = [ { id: "model-a", name: "Model A", enabled: true }, { id: "model-b", name: "Model B", enabled: false }, { id: "model-c", name: "Model C", enabled: false }, ]; const selector = await createSelector(models); selector.handleInput("\x01"); selector.handleInput("\r"); expect(models.map((model) => model.enabled)).toEqual([false, true, true]); expect(getMarkerStates(selector, models)).toEqual([false, true, true]); }); it("enables only the selected model after clearing all", async () => { const models = [ { id: "model-a", name: "Model A", enabled: true }, { id: "model-b", name: "Model B", enabled: true }, { id: "model-c", name: "Model C", enabled: true }, ]; const selector = await createSelector(models); selector.handleInput("\x18"); expect(models.map((model) => model.enabled)).toEqual([false, false, false]); expect(getMarkerStates(selector, models)).toEqual([false, false, false]); selector.handleInput("\r"); expect(models.map((model) => model.enabled)).toEqual([true, false, false]); expect(getMarkerStates(selector, models)).toEqual([true, false, false]); }); it("restores the all-enabled state after re-enabling the last disabled model", async () => { const models = [ { id: "model-a", name: "Model A", enabled: true }, { id: "model-b", name: "Model B", enabled: false }, { id: "model-c", name: "Model C", enabled: false }, ]; const selector = await createSelector(models); selector.handleInput("\x01"); // enable all -> null selector.handleInput("\r"); // disable model-a; enabled models re-sort first: [b, c, a] selector.handleInput("\x1b[B"); selector.handleInput("\x1b[B"); // move selection back to model-a selector.handleInput("\r"); // re-enable model-a expect(models.map((model) => model.enabled)).toEqual([true, true, true]); expect(getMarkerStates(selector, models)).toEqual([true, true, true]); expect(stripAnsi(selector.render(120).join("\n"))).toContain("all enabled"); }); });