112 lines
3.7 KiB
TypeScript
112 lines
3.7 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert";
|
|
import { resolveConfig } from "../src/config.js";
|
|
|
|
describe("resolveConfig", () => {
|
|
it("returns empty config when no sources are present", () => {
|
|
const config = resolveConfig({
|
|
existsSync: () => false,
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.deepStrictEqual(config.paths, {});
|
|
assert.strictEqual(config.defaultClient, undefined);
|
|
});
|
|
|
|
it("loads config from file", () => {
|
|
const config = resolveConfig({
|
|
existsSync: () => true,
|
|
readFileSync: () =>
|
|
JSON.stringify({
|
|
paths: { codex: "/file/codex", claude: "/file/claude" },
|
|
defaultClient: "claude",
|
|
}),
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.strictEqual(config.paths.codex, "/file/codex");
|
|
assert.strictEqual(config.paths.claude, "/file/claude");
|
|
assert.strictEqual(config.defaultClient, "claude");
|
|
});
|
|
|
|
it("overrides file config with env vars", () => {
|
|
const config = resolveConfig({
|
|
env: { AI_CLI_CODEX_PATH: "/env/codex" },
|
|
existsSync: () => true,
|
|
readFileSync: () => JSON.stringify({ paths: { codex: "/file/codex" } }),
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.strictEqual(config.paths.codex, "/env/codex");
|
|
});
|
|
|
|
it("overrides env vars with CLI flags", () => {
|
|
const config = resolveConfig({
|
|
flags: { "codex-path": "/flag/codex" },
|
|
env: { AI_CLI_CODEX_PATH: "/env/codex" },
|
|
existsSync: () => true,
|
|
readFileSync: () => JSON.stringify({ paths: { codex: "/file/codex" } }),
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.strictEqual(config.paths.codex, "/flag/codex");
|
|
});
|
|
|
|
it("falls back to PATH detection when config file is missing", () => {
|
|
const config = resolveConfig({
|
|
existsSync: () => false,
|
|
whichSync: (cmd) =>
|
|
cmd === "opencode" ? "/usr/bin/opencode" : undefined,
|
|
});
|
|
assert.strictEqual(config.paths.opencode, "/usr/bin/opencode");
|
|
assert.strictEqual(config.paths.codex, undefined);
|
|
assert.strictEqual(config.paths.claude, undefined);
|
|
});
|
|
|
|
it("respects full priority ordering: flag > env > file > PATH", () => {
|
|
const config = resolveConfig({
|
|
flags: {
|
|
"codex-path": "/flag/codex",
|
|
"claude-path": "/flag/claude",
|
|
"opencode-path": "/flag/opencode",
|
|
"default-client": "opencode",
|
|
},
|
|
env: {
|
|
AI_CLI_CODEX_PATH: "/env/codex",
|
|
AI_CLI_CLAUDE_PATH: "/env/claude",
|
|
AI_CLI_OPENCODE_PATH: "/env/opencode",
|
|
AI_CLI_DEFAULT_CLIENT: "claude",
|
|
},
|
|
existsSync: () => true,
|
|
readFileSync: () =>
|
|
JSON.stringify({
|
|
paths: {
|
|
codex: "/file/codex",
|
|
claude: "/file/claude",
|
|
opencode: "/file/opencode",
|
|
},
|
|
defaultClient: "codex",
|
|
}),
|
|
whichSync: (cmd) => `/path/${cmd}`,
|
|
});
|
|
assert.strictEqual(config.paths.codex, "/flag/codex");
|
|
assert.strictEqual(config.paths.claude, "/flag/claude");
|
|
assert.strictEqual(config.paths.opencode, "/flag/opencode");
|
|
assert.strictEqual(config.defaultClient, "opencode");
|
|
});
|
|
|
|
it("uses env var for default client when no flag is given", () => {
|
|
const config = resolveConfig({
|
|
env: { AI_CLI_DEFAULT_CLIENT: "claude" },
|
|
existsSync: () => false,
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.strictEqual(config.defaultClient, "claude");
|
|
});
|
|
|
|
it("uses file default client when no env var is given", () => {
|
|
const config = resolveConfig({
|
|
existsSync: () => true,
|
|
readFileSync: () => JSON.stringify({ defaultClient: "codex" }),
|
|
whichSync: () => undefined,
|
|
});
|
|
assert.strictEqual(config.defaultClient, "codex");
|
|
});
|
|
});
|