149 lines
4.4 KiB
TypeScript
149 lines
4.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
CANONICAL_API_KEY_SOURCES,
|
|
appendConfigFixLog,
|
|
maskKey,
|
|
resolveApiServerKeyWithSource,
|
|
} from "../src/main/config";
|
|
|
|
/**
|
|
* Source-aware variant of the precedence resolver. The plain
|
|
* `resolveApiServerKey` test in api-server-key-resolution.test.ts pins
|
|
* the precedence policy; this one pins the source tag, which the
|
|
* migration-on-read and config-health-audit features both depend on.
|
|
*/
|
|
|
|
describe("resolveApiServerKeyWithSource", () => {
|
|
const empty = {
|
|
configTopLevelProfile: null,
|
|
configTopLevelDefault: null,
|
|
envProfile: null,
|
|
envDefault: null,
|
|
apiServerTokenProfile: null,
|
|
apiServerTokenDefault: null,
|
|
};
|
|
|
|
it("returns null source when every candidate is empty", () => {
|
|
expect(resolveApiServerKeyWithSource(empty)).toEqual({
|
|
value: "",
|
|
source: null,
|
|
});
|
|
});
|
|
|
|
it("tags configTopLevelProfile when only that is set", () => {
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
...empty,
|
|
configTopLevelProfile: " sk-cfg-profile ",
|
|
}),
|
|
).toEqual({ value: "sk-cfg-profile", source: "configTopLevelProfile" });
|
|
});
|
|
|
|
it("tags envProfile when both env profile and api_server.token are set (env wins)", () => {
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
...empty,
|
|
envProfile: "sk-env-profile",
|
|
apiServerTokenProfile: "sk-token-profile",
|
|
}),
|
|
).toEqual({ value: "sk-env-profile", source: "envProfile" });
|
|
});
|
|
|
|
it("tags apiServerTokenProfile when only that is set", () => {
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
...empty,
|
|
apiServerTokenProfile: "sk-token-profile",
|
|
}),
|
|
).toEqual({
|
|
value: "sk-token-profile",
|
|
source: "apiServerTokenProfile",
|
|
});
|
|
});
|
|
|
|
it("falls through to apiServerTokenDefault when everything earlier is empty", () => {
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
...empty,
|
|
apiServerTokenDefault: "sk-token-default",
|
|
}),
|
|
).toEqual({
|
|
value: "sk-token-default",
|
|
source: "apiServerTokenDefault",
|
|
});
|
|
});
|
|
|
|
it("preserves the precedence order from resolveApiServerKey", () => {
|
|
// All six set — should pick configTopLevelProfile (first in order)
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
configTopLevelProfile: "a",
|
|
configTopLevelDefault: "b",
|
|
envProfile: "c",
|
|
envDefault: "d",
|
|
apiServerTokenProfile: "e",
|
|
apiServerTokenDefault: "f",
|
|
}),
|
|
).toEqual({ value: "a", source: "configTopLevelProfile" });
|
|
});
|
|
|
|
it("treats whitespace-only candidates as empty", () => {
|
|
expect(
|
|
resolveApiServerKeyWithSource({
|
|
...empty,
|
|
configTopLevelProfile: " ",
|
|
envProfile: "sk-real",
|
|
}),
|
|
).toEqual({ value: "sk-real", source: "envProfile" });
|
|
});
|
|
});
|
|
|
|
describe("CANONICAL_API_KEY_SOURCES", () => {
|
|
it("contains only the .env-backed sources", () => {
|
|
expect(CANONICAL_API_KEY_SOURCES.has("envProfile")).toBe(true);
|
|
expect(CANONICAL_API_KEY_SOURCES.has("envDefault")).toBe(true);
|
|
expect(CANONICAL_API_KEY_SOURCES.has("configTopLevelProfile")).toBe(false);
|
|
expect(CANONICAL_API_KEY_SOURCES.has("configTopLevelDefault")).toBe(false);
|
|
expect(CANONICAL_API_KEY_SOURCES.has("apiServerTokenProfile")).toBe(false);
|
|
expect(CANONICAL_API_KEY_SOURCES.has("apiServerTokenDefault")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("maskKey", () => {
|
|
it("returns empty string for empty input", () => {
|
|
expect(maskKey("")).toBe("");
|
|
});
|
|
|
|
it("returns generic mask for very short values", () => {
|
|
expect(maskKey("short")).toBe("***");
|
|
expect(maskKey("sk-12345")).toBe("***");
|
|
});
|
|
|
|
it("keeps first 4 + last 4 for longer values", () => {
|
|
expect(maskKey("sk-test-arc-codex-AAAA-BBBB-CCCC")).toBe("sk-t…CCCC");
|
|
expect(maskKey("OPENROUTER123456789")).toBe("OPEN…6789");
|
|
});
|
|
|
|
it("does not leak the middle even for medium-length keys", () => {
|
|
const masked = maskKey("sk-1234567890");
|
|
expect(masked).not.toContain("567");
|
|
expect(masked.startsWith("sk-1")).toBe(true);
|
|
expect(masked.endsWith("7890")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("appendConfigFixLog", () => {
|
|
it("never throws on bad input (writes are best-effort)", () => {
|
|
expect(() =>
|
|
appendConfigFixLog({
|
|
ts: Date.now(),
|
|
issueCode: "TEST_NOOP",
|
|
action: "migrate",
|
|
from: "configTopLevelProfile",
|
|
to: ".env",
|
|
valueMasked: "sk-t…CCCC",
|
|
}),
|
|
).not.toThrow();
|
|
});
|
|
});
|