repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/good-job/__tests__/settings.test.ts
Rawimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
createPiSession,
type PiSession,
} from "../../../test/fixture/create-pi-session.ts";
function extensionPath(): string {
return fileURLToPath(new URL("../index.ts", import.meta.url));
}
type Case = { user?: unknown; project?: unknown; untrusted?: boolean };
describe("good-job settings resolution", () => {
let session: PiSession | undefined;
let root: string | undefined;
afterEach(async () => {
await session?.dispose();
session = undefined;
vi.restoreAllMocks();
if (root) rmSync(root, { recursive: true, force: true });
root = undefined;
});
async function status(input: Case): Promise<string> {
root = mkdtempSync(path.join(tmpdir(), "pi-ext-good-job-settings-"));
if ("project" in input) {
const dir = path.join(root, ".pi");
mkdirSync(dir, { recursive: true });
writeFileSync(
path.join(dir, "settings.json"),
JSON.stringify(input.project),
);
}
session = await createPiSession({
cwd: root,
extensionPaths: [extensionPath()],
...("user" in input
? { userSettings: input.user as Record<string, unknown> }
: {}),
});
if (input.untrusted)
session.session.settingsManager.setProjectTrusted(false);
const runner = session.session.extensionRunner;
const gj = session.extensions[0]!.commands.get("gj")!;
const ctx = runner.createContext();
const notify = vi.spyOn(ctx.ui, "notify").mockImplementation(() => {});
await gj.handler("status", ctx as never);
return String(notify.mock.calls.at(-1)?.[0]);
}
const user = {
"good-job": { model: "user/model", thinkingLevel: "low" },
};
it.each([
["defaults", {}, "current", "provider default"],
["user", { user }, "user/model", "low"],
[
"project over user per key",
{ user, project: { "good-job": { thinkingLevel: "high" } } },
"user/model",
"high",
],
[
"untrusted project ignored",
{
user,
project: { "good-job": { model: "project/model" } },
untrusted: true,
},
"user/model",
"low",
],
[
"old goodJob key ignored",
{ user: { goodJob: { model: "old/model", thinkingLevel: "max" } } },
"current",
"provider default",
],
] satisfies [string, Case, string, string][])(
"%s",
async (_name, input, model, thinking) => {
const message = await status(input);
expect(message).toContain(`analysis model: ${model}`);
expect(message).toContain(`thinking: ${thinking}`);
},
);
it("resolves directory from settings", async () => {
const message = await status({
user: { "good-job": { directory: " gj-store " } },
});
expect(message).toContain(path.join(root ?? "", "gj-store"));
});
it.each([
[
"project thinkingLevel",
{ user, project: { "good-job": { thinkingLevel: "invalid" } } },
"Invalid good-job.thinkingLevel from project settings: must be minimal, low, medium, high, xhigh, or max",
],
[
"user model",
{ user: { "good-job": { model: "no-slash" } } },
"Invalid good-job.model from user settings: must be provider/model",
],
[
"user directory",
{ user: { "good-job": { directory: " " } } },
"Invalid good-job.directory from user settings: must be a non-empty path",
],
] satisfies [string, Case, string][])(
"rejects invalid %s without falling through",
async (_name, input, error) => {
await expect(status(input)).rejects.toThrow(error);
},
);
});