Files
openclaw/src/agents/model-auth-label.test.ts

169 lines
5.6 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
ensureAuthProfileStore: vi.fn(),
loadAuthProfileStoreWithoutExternalProfiles: vi.fn(),
resolveAuthProfileOrder: vi.fn(),
resolveAuthProfileDisplayLabel: vi.fn(),
resolveUsableCustomProviderApiKey: vi.fn(() => null),
resolveEnvApiKey: vi.fn(() => null),
readCodexCliCredentialsCached: vi.fn<() => unknown>(() => null),
}));
vi.mock("./auth-profiles.js", () => ({
ensureAuthProfileStore: mocks.ensureAuthProfileStore,
loadAuthProfileStoreWithoutExternalProfiles: mocks.loadAuthProfileStoreWithoutExternalProfiles,
resolveAuthProfileOrder: mocks.resolveAuthProfileOrder,
resolveAuthProfileDisplayLabel: mocks.resolveAuthProfileDisplayLabel,
}));
vi.mock("./model-auth.js", () => ({
resolveUsableCustomProviderApiKey: mocks.resolveUsableCustomProviderApiKey,
resolveEnvApiKey: mocks.resolveEnvApiKey,
}));
vi.mock("./cli-credentials.js", () => ({
readClaudeCliCredentialsCached: () => null,
readCodexCliCredentialsCached: mocks.readCodexCliCredentialsCached,
}));
let resolveModelAuthLabel: typeof import("./model-auth-label.js").resolveModelAuthLabel;
describe("resolveModelAuthLabel", () => {
beforeEach(async () => {
if (!resolveModelAuthLabel) {
({ resolveModelAuthLabel } = await import("./model-auth-label.js"));
}
mocks.ensureAuthProfileStore.mockReset();
mocks.loadAuthProfileStoreWithoutExternalProfiles.mockReset();
mocks.resolveAuthProfileOrder.mockReset();
mocks.resolveAuthProfileDisplayLabel.mockReset();
mocks.resolveUsableCustomProviderApiKey.mockReset();
mocks.resolveUsableCustomProviderApiKey.mockReturnValue(null);
mocks.resolveEnvApiKey.mockReset();
mocks.resolveEnvApiKey.mockReturnValue(null);
mocks.readCodexCliCredentialsCached.mockReset();
mocks.readCodexCliCredentialsCached.mockReturnValue(null);
});
it("does not include token value in label for token profiles", () => {
mocks.ensureAuthProfileStore.mockReturnValue({
version: 1,
profiles: {
"github-copilot:default": {
type: "token",
provider: "github-copilot",
token: "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // pragma: allowlist secret
tokenRef: { source: "env", provider: "default", id: "GITHUB_TOKEN" },
},
},
} as never);
mocks.resolveAuthProfileOrder.mockReturnValue(["github-copilot:default"]);
mocks.resolveAuthProfileDisplayLabel.mockReturnValue("github-copilot:default");
const label = resolveModelAuthLabel({
provider: "github-copilot",
cfg: {},
sessionEntry: { authProfileOverride: "github-copilot:default" } as never,
});
expect(label).toBe("token (github-copilot:default)");
expect(label).not.toContain("ghp_");
expect(label).not.toContain("ref(");
});
it("does not include api-key value in label for api-key profiles", () => {
const shortSecret = "abc123"; // pragma: allowlist secret
mocks.ensureAuthProfileStore.mockReturnValue({
version: 1,
profiles: {
"openai:default": {
type: "api_key",
provider: "openai",
key: shortSecret,
},
},
} as never);
mocks.resolveAuthProfileOrder.mockReturnValue(["openai:default"]);
mocks.resolveAuthProfileDisplayLabel.mockReturnValue("openai:default");
const label = resolveModelAuthLabel({
provider: "openai",
cfg: {},
sessionEntry: { authProfileOverride: "openai:default" } as never,
});
expect(label).toBe("api-key (openai:default)");
expect(label).not.toContain(shortSecret);
expect(label).not.toContain("...");
});
it("shows oauth type with profile label", () => {
mocks.ensureAuthProfileStore.mockReturnValue({
version: 1,
profiles: {
"anthropic:oauth": {
type: "oauth",
provider: "anthropic",
},
},
} as never);
mocks.resolveAuthProfileOrder.mockReturnValue(["anthropic:oauth"]);
mocks.resolveAuthProfileDisplayLabel.mockReturnValue("anthropic:oauth");
const label = resolveModelAuthLabel({
provider: "anthropic",
cfg: {},
sessionEntry: { authProfileOverride: "anthropic:oauth" } as never,
});
expect(label).toBe("oauth (anthropic:oauth)");
});
it("shows codex cli auth for codex provider without auth profiles", () => {
mocks.ensureAuthProfileStore.mockReturnValue({
version: 1,
profiles: {},
} as never);
mocks.resolveAuthProfileOrder.mockReturnValue([]);
mocks.readCodexCliCredentialsCached.mockReturnValue({
type: "oauth",
provider: "openai-codex",
access: "token",
refresh: "refresh",
expires: Date.now() + 60_000,
});
const label = resolveModelAuthLabel({
provider: "codex",
cfg: {},
});
expect(label).toBe("oauth (codex-cli)");
});
it("can skip external auth profile overlays for status labels", () => {
mocks.loadAuthProfileStoreWithoutExternalProfiles.mockReturnValue({
version: 1,
profiles: {
"anthropic:oauth": {
type: "oauth",
provider: "anthropic",
},
},
} as never);
mocks.resolveAuthProfileOrder.mockReturnValue(["anthropic:oauth"]);
mocks.resolveAuthProfileDisplayLabel.mockReturnValue("anthropic:oauth");
const label = resolveModelAuthLabel({
provider: "anthropic",
cfg: {},
includeExternalProfiles: false,
});
expect(label).toBe("oauth (anthropic:oauth)");
expect(mocks.loadAuthProfileStoreWithoutExternalProfiles).toHaveBeenCalledOnce();
expect(mocks.ensureAuthProfileStore).not.toHaveBeenCalled();
});
});