/** * thinking-level.ts unit tests: the conversation-time pickers' short-name lookup and the * selectable list — both pickers offer only low/medium/high/xhigh (many models cannot disable * thinking; there is no "follow config" row — the session picker auto-follows the Agent * config by initializing its display to it), while "none" stays a displayable stored value; * "" (internally "untouched"/no override) and a legacy meta's "default" resolve to null so * callers substitute the config level or a placeholder. */ import { describe, expect, it } from "vitest"; import { SELECTABLE_THINKING_LEVELS, THINKING_LEVELS, thinkingLevelLabel, thinkingLevelOptionsFor, } from "../src/features/chat/thinking-level"; /** Mirrors the shape of S.chat.thinkingLevelNames. */ const NAMES: Readonly> = { none: "None", low: "Low", medium: "Medium", high: "High", xhigh: "Extreme High", }; describe("thinking level lists", () => { it("offers only low/medium/high/xhigh — no 'none' (many models cannot disable thinking)", () => { expect(SELECTABLE_THINKING_LEVELS).toEqual(["low", "medium", "high", "xhigh"]); expect(SELECTABLE_THINKING_LEVELS).not.toContain("none"); }); it("keeps all five stored levels displayable (a legacy 'none' is shown, never offered)", () => { expect(THINKING_LEVELS).toEqual(["none", "low", "medium", "high", "xhigh"]); expect(THINKING_LEVELS.map((l) => thinkingLevelLabel(NAMES, l))).toEqual([ "None", "Low", "Medium", "High", "Extreme High", ]); }); }); describe("thinkingLevelLabel", () => { it("returns null for non-levels: '' (untouched/no override), a legacy meta's 'default', unknown, null", () => { expect(thinkingLevelLabel(NAMES, "")).toBeNull(); expect(thinkingLevelLabel(NAMES, "default")).toBeNull(); expect(thinkingLevelLabel(NAMES, "ultra")).toBeNull(); expect(thinkingLevelLabel(NAMES, null)).toBeNull(); expect(thinkingLevelLabel(NAMES, undefined)).toBeNull(); }); it("falls back to the raw value if the name table misses a level (defensive)", () => { expect(thinkingLevelLabel({}, "medium")).toBe("medium"); }); }); describe("thinkingLevelOptionsFor (agent-settings dropdown assembly)", () => { /** Mirrors the shape of S.agent.thinkingLevelOptions after the none row's removal. */ const OPTIONS: ReadonlyArray = [ ["", "Send no override."], ["low", "Low tier."], ["medium", "Medium tier."], ["high", "High tier."], ["xhigh", "Extra-high tier."], ]; it("filters the '' inherit row and keeps dictionary order; no none row normally", () => { for (const stored of [undefined, "", "medium", "xhigh"]) { const rows = thinkingLevelOptionsFor(OPTIONS, "legacy none", stored); expect(rows.map((r) => r.value)).toEqual(["low", "medium", "high", "xhigh"]); expect(rows.some((r) => r.value === "none")).toBe(false); expect(rows[0]).toMatchObject({ triggerLabel: "low", label: "low", description: "Low tier.", }); } }); it("appends a display-only none row when the persisted config stores none (backward compat)", () => { const rows = thinkingLevelOptionsFor(OPTIONS, "legacy none", "none"); expect(rows.map((r) => r.value)).toEqual(["low", "medium", "high", "xhigh", "none"]); expect(rows.at(-1)).toEqual({ value: "none", triggerLabel: "none", label: "none", description: "legacy none", }); }); });