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 { afterEach, describe, expect, it } from "vitest";
import { createTestSession, type TestSession } from "../../../test/harness";
const extensionPath = path.resolve(import.meta.dirname, "../index.ts");
type Case = { user?: unknown; project?: unknown; untrusted?: boolean };
describe("good-job settings resolution", () => {
let t: TestSession | undefined;
let root: string | undefined;
afterEach(() => {
t?.dispose();
t = undefined;
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-"));
const write = (dir: string, value: unknown) => {
mkdirSync(dir, { recursive: true });
writeFileSync(path.join(dir, "settings.json"), JSON.stringify(value));
};
if ("user" in input)
write(path.join(root, ".test-home/.pi/agent"), input.user);
if ("project" in input) write(path.join(root, ".pi"), input.project);
const session = await createTestSession({
cwd: root,
extensions: [extensionPath],
});
t = session;
if (input.untrusted)
session.session.settingsManager.setProjectTrusted(false);
const runner = session.session.extensionRunner;
const gj = runner.extensions[0].commands.get("gj");
await gj.handler("status", runner.createContext() as never);
return String(session.events.uiCallsFor("notify").at(-1)?.args[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);
},
);
});