import { DEFAULT_OPENAI_MODEL, SystemRole } from "@capakraken/shared"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const { createAuditEntry, testSmtpConnection, generateGeminiImage, parseGeminiError, } = vi.hoisted(() => ({ createAuditEntry: vi.fn(), testSmtpConnection: vi.fn(), generateGeminiImage: vi.fn(), parseGeminiError: vi.fn((error: unknown) => `parsed:${String(error)}`), })); vi.mock("../lib/audit.js", () => ({ createAuditEntry, })); vi.mock("../lib/email.js", () => ({ testSmtpConnection, })); vi.mock("../gemini-client.js", () => ({ generateGeminiImage, parseGeminiError, })); import { clearStoredRuntimeSecrets, getAiConfiguredStatus, getSystemSettingsView, testSettingsGeminiConnection, testSettingsSmtpConnection, updateSystemSettings, } from "../router/settings-procedure-support.js"; function createAdminContext(db: Record) { return { db: db as never, dbUser: { id: "admin_1", systemRole: SystemRole.ADMIN, permissionOverrides: null, }, }; } describe("settings procedure support", () => { beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.unstubAllEnvs(); }); it("builds the system settings view model from db and runtime state", async () => { vi.stubEnv("OPENAI_API_KEY", "env-openai-key"); vi.stubEnv("SMTP_PASSWORD", "env-smtp-password"); const result = await getSystemSettingsView(createAdminContext({ systemSettings: { findUnique: vi.fn().mockResolvedValue({ aiProvider: "openai", azureOpenAiApiKey: null, smtpPassword: null, }), }, })); expect(result.hasApiKey).toBe(true); expect(result.hasSmtpPassword).toBe(true); expect(result.aiProvider).toBe("openai"); expect(result.defaultSummaryPrompt).toBeTypeOf("string"); }); it("updates settings without persisting incoming secret fields and writes an audit entry", async () => { const findUnique = vi.fn().mockResolvedValue({ id: "singleton", aiProvider: "azure", azureOpenAiApiKey: "secret", }); const upsert = vi.fn().mockResolvedValue({}); const result = await updateSystemSettings(createAdminContext({ systemSettings: { findUnique, upsert, }, }), { aiProvider: "openai", azureOpenAiDeployment: DEFAULT_OPENAI_MODEL, azureOpenAiApiKey: "should-be-ignored", smtpPassword: "also-ignored", }); expect(result).toEqual({ ok: true, ignoredSecretFields: ["azureOpenAiApiKey", "smtpPassword"], secretStorageMode: "environment-only", }); expect(upsert).toHaveBeenCalledWith({ where: { id: "singleton" }, create: { id: "singleton", aiProvider: "openai", azureOpenAiDeployment: DEFAULT_OPENAI_MODEL, }, update: { aiProvider: "openai", azureOpenAiDeployment: DEFAULT_OPENAI_MODEL, }, }); expect(createAuditEntry).toHaveBeenCalledWith(expect.objectContaining({ entityType: "SystemSettings", action: "UPDATE", after: expect.objectContaining({ aiProvider: "openai", azureOpenAiDeployment: DEFAULT_OPENAI_MODEL, }), })); }); it("clears only legacy runtime secrets that are still stored", async () => { const update = vi.fn().mockResolvedValue({}); const result = await clearStoredRuntimeSecrets(createAdminContext({ systemSettings: { findUnique: vi.fn().mockResolvedValue({ azureOpenAiApiKey: "db-key", azureDalleApiKey: null, geminiApiKey: "db-gemini", smtpPassword: null, anonymizationSeed: "seed", }), update, }, })); expect(result).toEqual({ ok: true, clearedFields: ["azureOpenAiApiKey", "geminiApiKey", "anonymizationSeed"], }); expect(update).toHaveBeenCalledWith({ where: { id: "singleton" }, data: { azureOpenAiApiKey: null, geminiApiKey: null, anonymizationSeed: null, }, }); }); it("tests smtp and gemini connections with audited outcomes", async () => { testSmtpConnection.mockResolvedValue({ ok: true }); generateGeminiImage.mockResolvedValue("data:image/png;base64,abc123"); const db = { systemSettings: { findUnique: vi.fn().mockResolvedValue({ geminiApiKey: "gem-key", geminiModel: "gem-model", }), }, }; const ctx = createAdminContext(db); expect(await testSettingsSmtpConnection(ctx)).toEqual({ ok: true }); expect(await testSettingsGeminiConnection(ctx)).toEqual({ ok: true, model: "gem-model", preview: "data:image/png;base64,abc123...", }); expect(createAuditEntry).toHaveBeenCalledTimes(2); }); it("reads the ai configured status from runtime-resolved settings", async () => { vi.stubEnv("OPENAI_API_KEY", "env-openai-key"); const result = await getAiConfiguredStatus(createAdminContext({ systemSettings: { findUnique: vi.fn().mockResolvedValue({ aiProvider: "openai", azureOpenAiDeployment: DEFAULT_OPENAI_MODEL, azureOpenAiApiKey: null, }), }, })); expect(result).toEqual({ configured: true }); }); });