test: add coverage for listK8sModels CLI fetch and fallback

chore: bump version to 0.1.32

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-26 02:07:51 +00:00
committed by Hugh Commit [agent]
parent 168161148c
commit da1b55d233
2 changed files with 79 additions and 1 deletions
+78
View File
@@ -0,0 +1,78 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
const execMock = vi.fn();
vi.mock("child_process", () => ({
exec: (cmd: string, opts: unknown, cb: (err: Error | null, result: { stdout: string; stderr: string }) => void) => {
execMock(cmd, opts, cb);
},
}));
const { listK8sModels } = await import("./models.js");
function mockExecResult(stdout: string) {
execMock.mockImplementation((_cmd, _opts, cb) => {
cb(null, { stdout, stderr: "" });
});
}
function mockExecError(err: Error) {
execMock.mockImplementation((_cmd, _opts, cb) => {
cb(err, { stdout: "", stderr: "" });
});
}
describe("listK8sModels", () => {
beforeEach(() => {
execMock.mockReset();
});
it("parses opencode models output into AdapterModel entries", async () => {
mockExecResult(
[
"anthropic/claude-opus-4-7",
"openai/gpt-4o",
"google/gemini-2.5-pro",
].join("\n"),
);
const models = await listK8sModels();
expect(models).toHaveLength(3);
expect(models[0]).toEqual({ id: "anthropic/claude-opus-4-7", label: "claude opus 4 7" });
expect(models[1]).toEqual({ id: "openai/gpt-4o", label: "gpt 4o" });
expect(models[2]).toEqual({ id: "google/gemini-2.5-pro", label: "gemini 2.5 pro" });
});
it("ignores blank lines and trims whitespace", async () => {
mockExecResult("\nanthropic/claude-opus-4-7\n\n openai/gpt-4o \n\n");
const models = await listK8sModels();
expect(models.map((m) => m.id)).toEqual([
"anthropic/claude-opus-4-7",
"openai/gpt-4o",
]);
});
it("invokes opencode models with a timeout", async () => {
mockExecResult("anthropic/claude-opus-4-7");
await listK8sModels();
expect(execMock).toHaveBeenCalledTimes(1);
const [cmd, opts] = execMock.mock.calls[0];
expect(cmd).toBe("opencode models");
expect(opts).toMatchObject({ timeout: 30_000 });
});
it("falls back to the static list when the CLI fails", async () => {
mockExecError(new Error("ENOENT: opencode not found"));
const models = await listK8sModels();
expect(models.length).toBeGreaterThan(0);
expect(models.map((m) => m.id)).toContain("anthropic/claude-opus-4-7");
expect(models.map((m) => m.id)).toContain("openai/gpt-4o");
});
});