build: remember last models

This commit is contained in:
2026-03-23 16:54:51 +05:30
parent fabd2f6519
commit af5d888f56
10 changed files with 204 additions and 43 deletions
+86
View File
@@ -7,6 +7,7 @@ import {
spyOn,
test,
} from "bun:test";
import * as fs from "node:fs";
import * as os from "node:os";
import {
createWindowBaseName,
@@ -15,13 +16,16 @@ import {
formatInvalidModelError,
getBinaryName,
getSessionPath,
getSettingsPath,
getWorktreePath,
getWorktreesForSession,
launchModelInWindow,
levenshtein,
loadSettings,
normalizeModels,
runCommand,
sanitizeName,
saveSettings,
shellQuote,
suggestModels,
undoWorktree,
@@ -484,4 +488,86 @@ describe("core utils", () => {
delete process.env.OPENCODE_MULTI_MODEL_BINARY;
});
});
describe("getSettingsPath", () => {
test("returns correct settings path", () => {
spyOn(os, "homedir").mockReturnValue("/home/user");
expect(getSettingsPath()).toBe(
"/home/user/.config/opencode-multi-model/settings.json",
);
});
});
describe("loadSettings", () => {
let readFileMock: ReturnType<typeof spyOn>;
beforeEach(() => {
spyOn(os, "homedir").mockReturnValue("/home/user");
readFileMock = spyOn(fs.promises, "readFile");
});
test("returns default settings when file does not exist", async () => {
readFileMock.mockRejectedValue(new Error("ENOENT"));
const result = await loadSettings();
expect(result).toEqual({ lastModels: [] });
});
test("returns default settings when file has invalid JSON", async () => {
readFileMock.mockResolvedValue("not valid json");
const result = await loadSettings();
expect(result).toEqual({ lastModels: [] });
});
test("returns default settings when lastModels is not an array", async () => {
readFileMock.mockResolvedValue(
JSON.stringify({ lastModels: "not array" }),
);
const result = await loadSettings();
expect(result).toEqual({ lastModels: [] });
});
test("parses valid settings file", async () => {
readFileMock.mockResolvedValue(
JSON.stringify({ lastModels: ["model1", "model2"] }),
);
const result = await loadSettings();
expect(result).toEqual({ lastModels: ["model1", "model2"] });
});
});
describe("saveSettings", () => {
let mkdirMock: ReturnType<typeof spyOn>;
let writeFileMock: ReturnType<typeof spyOn>;
beforeEach(() => {
spyOn(os, "homedir").mockReturnValue("/home/user");
mkdirMock = spyOn(fs.promises, "mkdir");
writeFileMock = spyOn(fs.promises, "writeFile");
});
test("creates directory if it does not exist", async () => {
mkdirMock.mockResolvedValue(undefined);
writeFileMock.mockResolvedValue(undefined);
await saveSettings({ lastModels: ["model1"] });
expect(mkdirMock).toHaveBeenCalledWith(
"/home/user/.config/opencode-multi-model",
{ recursive: true },
);
});
test("writes settings with correct content", async () => {
mkdirMock.mockResolvedValue(undefined);
writeFileMock.mockResolvedValue(undefined);
await saveSettings({ lastModels: ["model1", "model2"] });
expect(writeFileMock).toHaveBeenCalledWith(
"/home/user/.config/opencode-multi-model/settings.json",
JSON.stringify({ lastModels: ["model1", "model2"] }, null, 2),
"utf-8",
);
});
});
});