mirror of https://github.com/openclaw/openclaw.git
refactor: share auth overview and fetch test helpers
This commit is contained in:
parent
985be2a864
commit
94e748086c
|
|
@ -1,7 +1,28 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { NON_ENV_SECRETREF_MARKER } from "../../agents/model-auth-markers.js";
|
||||
import { withEnv } from "../../test-utils/env.js";
|
||||
import { resolveProviderAuthOverview } from "./list.auth-overview.js";
|
||||
|
||||
function resolveOpenAiOverview(apiKey: string) {
|
||||
return resolveProviderAuthOverview({
|
||||
provider: "openai",
|
||||
cfg: {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
api: "openai-completions",
|
||||
apiKey,
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
store: { version: 1, profiles: {} } as never,
|
||||
modelsPath: "/tmp/models.json",
|
||||
});
|
||||
}
|
||||
|
||||
describe("resolveProviderAuthOverview", () => {
|
||||
it("does not throw when token profile only has tokenRef", () => {
|
||||
const overview = resolveProviderAuthOverview({
|
||||
|
|
@ -24,23 +45,9 @@ describe("resolveProviderAuthOverview", () => {
|
|||
});
|
||||
|
||||
it("renders marker-backed models.json auth as marker detail", () => {
|
||||
const overview = resolveProviderAuthOverview({
|
||||
provider: "openai",
|
||||
cfg: {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
api: "openai-completions",
|
||||
apiKey: NON_ENV_SECRETREF_MARKER,
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
store: { version: 1, profiles: {} } as never,
|
||||
modelsPath: "/tmp/models.json",
|
||||
});
|
||||
const overview = withEnv({ OPENAI_API_KEY: undefined }, () =>
|
||||
resolveOpenAiOverview(NON_ENV_SECRETREF_MARKER),
|
||||
);
|
||||
|
||||
expect(overview.effective.kind).toBe("missing");
|
||||
expect(overview.effective.detail).toBe("missing");
|
||||
|
|
@ -48,23 +55,9 @@ describe("resolveProviderAuthOverview", () => {
|
|||
});
|
||||
|
||||
it("keeps env-var-shaped models.json values masked to avoid accidental plaintext exposure", () => {
|
||||
const overview = resolveProviderAuthOverview({
|
||||
provider: "openai",
|
||||
cfg: {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
api: "openai-completions",
|
||||
apiKey: "OPENAI_API_KEY", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
store: { version: 1, profiles: {} } as never,
|
||||
modelsPath: "/tmp/models.json",
|
||||
});
|
||||
const overview = withEnv({ OPENAI_API_KEY: undefined }, () =>
|
||||
resolveOpenAiOverview("OPENAI_API_KEY"),
|
||||
);
|
||||
|
||||
expect(overview.effective.kind).toBe("missing");
|
||||
expect(overview.effective.detail).toBe("missing");
|
||||
|
|
@ -76,23 +69,7 @@ describe("resolveProviderAuthOverview", () => {
|
|||
const prior = process.env.OPENAI_API_KEY;
|
||||
process.env.OPENAI_API_KEY = "sk-openai-from-env"; // pragma: allowlist secret
|
||||
try {
|
||||
const overview = resolveProviderAuthOverview({
|
||||
provider: "openai",
|
||||
cfg: {
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
api: "openai-completions",
|
||||
apiKey: "OPENAI_API_KEY", // pragma: allowlist secret
|
||||
models: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
store: { version: 1, profiles: {} } as never,
|
||||
modelsPath: "/tmp/models.json",
|
||||
});
|
||||
const overview = resolveOpenAiOverview("OPENAI_API_KEY");
|
||||
expect(overview.effective.kind).toBe("env");
|
||||
expect(overview.effective.detail).not.toContain("OPENAI_API_KEY");
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@ import { botCtorSpy } from "./bot.create-telegram-bot.test-harness.js";
|
|||
import { createTelegramBot } from "./bot.js";
|
||||
import { getTelegramNetworkErrorOrigin } from "./network-errors.js";
|
||||
|
||||
function createWrappedTelegramClientFetch(proxyFetch: typeof fetch) {
|
||||
const shutdown = new AbortController();
|
||||
botCtorSpy.mockClear();
|
||||
createTelegramBot({
|
||||
token: "tok",
|
||||
fetchAbortSignal: shutdown.signal,
|
||||
proxyFetch,
|
||||
});
|
||||
const clientFetch = (botCtorSpy.mock.calls.at(-1)?.[1] as { client?: { fetch?: unknown } })
|
||||
?.client?.fetch as (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||
expect(clientFetch).toBeTypeOf("function");
|
||||
return { clientFetch, shutdown };
|
||||
}
|
||||
|
||||
describe("createTelegramBot fetch abort", () => {
|
||||
it("aborts wrapped client fetch when fetchAbortSignal aborts", async () => {
|
||||
const shutdown = new AbortController();
|
||||
const fetchSpy = vi.fn(
|
||||
(_input: RequestInfo | URL, init?: RequestInit) =>
|
||||
new Promise<AbortSignal>((resolve) => {
|
||||
|
|
@ -13,15 +26,9 @@ describe("createTelegramBot fetch abort", () => {
|
|||
signal.addEventListener("abort", () => resolve(signal), { once: true });
|
||||
}),
|
||||
);
|
||||
botCtorSpy.mockClear();
|
||||
createTelegramBot({
|
||||
token: "tok",
|
||||
fetchAbortSignal: shutdown.signal,
|
||||
proxyFetch: fetchSpy as unknown as typeof fetch,
|
||||
});
|
||||
const clientFetch = (botCtorSpy.mock.calls.at(-1)?.[1] as { client?: { fetch?: unknown } })
|
||||
?.client?.fetch as (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||
expect(clientFetch).toBeTypeOf("function");
|
||||
const { clientFetch, shutdown } = createWrappedTelegramClientFetch(
|
||||
fetchSpy as unknown as typeof fetch,
|
||||
);
|
||||
|
||||
const observedSignalPromise = clientFetch("https://example.test");
|
||||
shutdown.abort(new Error("shutdown"));
|
||||
|
|
@ -32,7 +39,6 @@ describe("createTelegramBot fetch abort", () => {
|
|||
});
|
||||
|
||||
it("tags wrapped Telegram fetch failures with the Bot API method", async () => {
|
||||
const shutdown = new AbortController();
|
||||
const fetchError = Object.assign(new TypeError("fetch failed"), {
|
||||
cause: Object.assign(new Error("connect timeout"), {
|
||||
code: "UND_ERR_CONNECT_TIMEOUT",
|
||||
|
|
@ -41,15 +47,7 @@ describe("createTelegramBot fetch abort", () => {
|
|||
const fetchSpy = vi.fn(async () => {
|
||||
throw fetchError;
|
||||
});
|
||||
botCtorSpy.mockClear();
|
||||
createTelegramBot({
|
||||
token: "tok",
|
||||
fetchAbortSignal: shutdown.signal,
|
||||
proxyFetch: fetchSpy as unknown as typeof fetch,
|
||||
});
|
||||
const clientFetch = (botCtorSpy.mock.calls.at(-1)?.[1] as { client?: { fetch?: unknown } })
|
||||
?.client?.fetch as (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||
expect(clientFetch).toBeTypeOf("function");
|
||||
const { clientFetch } = createWrappedTelegramClientFetch(fetchSpy as unknown as typeof fetch);
|
||||
|
||||
await expect(clientFetch("https://api.telegram.org/bot123456:ABC/getUpdates")).rejects.toBe(
|
||||
fetchError,
|
||||
|
|
@ -61,7 +59,6 @@ describe("createTelegramBot fetch abort", () => {
|
|||
});
|
||||
|
||||
it("preserves the original fetch error when tagging cannot attach metadata", async () => {
|
||||
const shutdown = new AbortController();
|
||||
const frozenError = Object.freeze(
|
||||
Object.assign(new TypeError("fetch failed"), {
|
||||
cause: Object.assign(new Error("connect timeout"), {
|
||||
|
|
@ -72,15 +69,7 @@ describe("createTelegramBot fetch abort", () => {
|
|||
const fetchSpy = vi.fn(async () => {
|
||||
throw frozenError;
|
||||
});
|
||||
botCtorSpy.mockClear();
|
||||
createTelegramBot({
|
||||
token: "tok",
|
||||
fetchAbortSignal: shutdown.signal,
|
||||
proxyFetch: fetchSpy as unknown as typeof fetch,
|
||||
});
|
||||
const clientFetch = (botCtorSpy.mock.calls.at(-1)?.[1] as { client?: { fetch?: unknown } })
|
||||
?.client?.fetch as (input: RequestInfo | URL, init?: RequestInit) => Promise<unknown>;
|
||||
expect(clientFetch).toBeTypeOf("function");
|
||||
const { clientFetch } = createWrappedTelegramClientFetch(fetchSpy as unknown as typeof fetch);
|
||||
|
||||
await expect(clientFetch("https://api.telegram.org/bot123456:ABC/getUpdates")).rejects.toBe(
|
||||
frozenError,
|
||||
|
|
|
|||
Loading…
Reference in New Issue