From 67f57e2791e9f1cecd7792aafcca25633e07506d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Wed, 1 Apr 2026 00:44:16 +0200 Subject: [PATCH] test(api): cover ai client helpers --- packages/api/src/__tests__/ai-client.test.ts | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 packages/api/src/__tests__/ai-client.test.ts diff --git a/packages/api/src/__tests__/ai-client.test.ts b/packages/api/src/__tests__/ai-client.test.ts new file mode 100644 index 0000000..7d698e8 --- /dev/null +++ b/packages/api/src/__tests__/ai-client.test.ts @@ -0,0 +1,63 @@ +import { DEFAULT_OPENAI_MODEL } from "@capakraken/shared"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { loggedAiCall, sanitizeDiagnosticError } from "../ai-client.js"; +import { logger } from "../lib/logger.js"; + +vi.mock("../lib/logger.js", () => ({ + logger: { + error: vi.fn(), + warn: vi.fn(), + info: vi.fn(), + debug: vi.fn(), + }, +})); + +describe("ai-client diagnostics", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("redacts URLs and secret-like tokens from diagnostics", () => { + const diagnostic = sanitizeDiagnosticError( + new Error( + "Request failed at https://example.openai.azure.com/path?api-key=topsecret with Bearer sk-super-secret", + ), + ); + + expect(diagnostic).toContain(""); + expect(diagnostic).toContain(""); + expect(diagnostic).not.toContain("https://example.openai.azure.com"); + expect(diagnostic).not.toContain("sk-super-secret"); + expect(diagnostic).not.toContain("topsecret"); + }); + + it("logs sanitized diagnostics when upstream AI calls fail", async () => { + const upstreamError = new Error( + "upstream 404 from https://example.openai.azure.com/openai/deployments/foo?api-key=topsecret with Bearer sk-secret", + ); + + await expect( + loggedAiCall("azure", DEFAULT_OPENAI_MODEL, 123, async () => { + throw upstreamError; + }), + ).rejects.toBe(upstreamError); + + expect(logger.warn).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "azure", + model: DEFAULT_OPENAI_MODEL, + promptLength: 123, + responseTimeMs: expect.any(Number), + errorMessage: expect.any(String), + }), + "External API call failed", + ); + + const payload = vi.mocked(logger.warn).mock.calls[0]?.[0]; + expect(payload?.errorMessage).toContain(""); + expect(payload?.errorMessage).toContain(""); + expect(payload?.errorMessage).not.toContain("https://example.openai.azure.com"); + expect(payload?.errorMessage).not.toContain("sk-secret"); + expect(payload?.errorMessage).not.toContain("topsecret"); + }); +});