import { beforeEach, describe, expect, it, vi } from "vitest"; import { AgentConfigService } from "./agent-config.service"; import { PrismaService } from "../prisma/prisma.service"; import { CryptoService } from "../crypto/crypto.service"; describe("AgentConfigService", () => { let service: AgentConfigService; const mockPrismaService = { userAgentConfig: { findUnique: vi.fn(), }, llmProvider: { findMany: vi.fn(), }, userContainer: { findUnique: vi.fn(), findMany: vi.fn(), }, systemContainer: { findUnique: vi.fn(), findMany: vi.fn(), }, }; const mockCryptoService = { isEncrypted: vi.fn((value: string) => value.startsWith("enc:")), decrypt: vi.fn((value: string) => value.replace(/^enc:/, "")), }; beforeEach(() => { vi.clearAllMocks(); service = new AgentConfigService( mockPrismaService as unknown as PrismaService, mockCryptoService as unknown as CryptoService ); }); it("generateUserConfig returns valid openclaw.json structure", async () => { mockPrismaService.userAgentConfig.findUnique.mockResolvedValue({ id: "cfg-1", userId: "user-1", primaryModel: "my-zai/glm-5", }); mockPrismaService.userContainer.findUnique.mockResolvedValue({ id: "container-1", userId: "user-1", gatewayPort: 19001, }); mockPrismaService.llmProvider.findMany.mockResolvedValue([ { id: "provider-1", userId: "user-1", name: "my-zai", displayName: "Z.ai", type: "zai", baseUrl: "https://api.z.ai/v1", apiKey: "enc:secret-zai-key", apiType: "openai-completions", models: [{ id: "glm-5" }], isActive: true, createdAt: new Date(), updatedAt: new Date(), }, ]); const result = await service.generateUserConfig("user-1"); expect(result).toEqual({ gateway: { mode: "local", port: 19001, bind: "lan", auth: { mode: "token" }, http: { endpoints: { chatCompletions: { enabled: true }, }, }, }, agents: { defaults: { model: { primary: "my-zai/glm-5", }, }, }, models: { providers: { "my-zai": { apiKey: "secret-zai-key", baseUrl: "https://api.z.ai/v1", models: { "glm-5": {}, }, }, }, }, }); }); it("generateUserConfig decrypts API keys correctly", async () => { mockPrismaService.userAgentConfig.findUnique.mockResolvedValue({ id: "cfg-1", userId: "user-1", primaryModel: "openai-work/gpt-4.1", }); mockPrismaService.userContainer.findUnique.mockResolvedValue({ id: "container-1", userId: "user-1", gatewayPort: 18789, }); mockPrismaService.llmProvider.findMany.mockResolvedValue([ { id: "provider-1", userId: "user-1", name: "openai-work", displayName: "OpenAI Work", type: "openai", baseUrl: "https://api.openai.com/v1", apiKey: "enc:encrypted-openai-key", apiType: "openai-completions", models: [{ id: "gpt-4.1" }], isActive: true, createdAt: new Date(), updatedAt: new Date(), }, ]); const result = await service.generateUserConfig("user-1"); expect(mockCryptoService.decrypt).toHaveBeenCalledWith("enc:encrypted-openai-key"); expect(result.models.providers["openai-work"]?.apiKey).toBe("encrypted-openai-key"); }); it("generateUserConfig handles user with no providers", async () => { mockPrismaService.userAgentConfig.findUnique.mockResolvedValue({ id: "cfg-1", userId: "user-2", primaryModel: "openai/gpt-4o-mini", }); mockPrismaService.userContainer.findUnique.mockResolvedValue({ id: "container-2", userId: "user-2", gatewayPort: null, }); mockPrismaService.llmProvider.findMany.mockResolvedValue([]); const result = await service.generateUserConfig("user-2"); expect(result.models.providers).toEqual({}); expect(result.gateway.port).toBe(18789); }); it("validateContainerToken returns correct type for user container", async () => { mockPrismaService.userContainer.findMany.mockResolvedValue([ { id: "user-container-1", gatewayToken: "enc:user-token-1", }, ]); mockPrismaService.systemContainer.findMany.mockResolvedValue([]); const result = await service.validateContainerToken("user-token-1"); expect(result).toEqual({ type: "user", id: "user-container-1", }); }); it("validateContainerToken returns correct type for system container", async () => { mockPrismaService.userContainer.findMany.mockResolvedValue([]); mockPrismaService.systemContainer.findMany.mockResolvedValue([ { id: "system-container-1", gatewayToken: "enc:system-token-1", }, ]); const result = await service.validateContainerToken("system-token-1"); expect(result).toEqual({ type: "system", id: "system-container-1", }); }); it("validateContainerToken returns null for invalid token", async () => { mockPrismaService.userContainer.findMany.mockResolvedValue([ { id: "user-container-1", gatewayToken: "enc:user-token-1", }, ]); mockPrismaService.systemContainer.findMany.mockResolvedValue([ { id: "system-container-1", gatewayToken: "enc:system-token-1", }, ]); const result = await service.validateContainerToken("no-match"); expect(result).toBeNull(); }); });