Files
stack/apps/orchestrator/src/api/agent-providers/agent-providers.service.spec.ts
Jason Woltje bcada71e88
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
feat(orchestrator): add AgentProviderConfig CRUD API
2026-03-07 13:22:56 -06:00

212 lines
6.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { NotFoundException } from "@nestjs/common";
import { AgentProvidersService } from "./agent-providers.service";
import { PrismaService } from "../../prisma/prisma.service";
describe("AgentProvidersService", () => {
let service: AgentProvidersService;
let prisma: {
agentProviderConfig: {
findMany: ReturnType<typeof vi.fn>;
findUnique: ReturnType<typeof vi.fn>;
create: ReturnType<typeof vi.fn>;
update: ReturnType<typeof vi.fn>;
delete: ReturnType<typeof vi.fn>;
};
};
beforeEach(() => {
prisma = {
agentProviderConfig: {
findMany: vi.fn(),
findUnique: vi.fn(),
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
},
};
service = new AgentProvidersService(prisma as unknown as PrismaService);
});
it("lists all provider configs", async () => {
const expected = [
{
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Primary",
provider: "openai",
gatewayUrl: "https://gateway.example.com",
credentials: {},
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
},
];
prisma.agentProviderConfig.findMany.mockResolvedValue(expected);
const result = await service.list();
expect(prisma.agentProviderConfig.findMany).toHaveBeenCalledWith({
orderBy: [{ createdAt: "desc" }, { id: "desc" }],
});
expect(result).toEqual(expected);
});
it("returns a single provider config", async () => {
const expected = {
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Primary",
provider: "openai",
gatewayUrl: "https://gateway.example.com",
credentials: { apiKeyRef: "vault:openai" },
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
};
prisma.agentProviderConfig.findUnique.mockResolvedValue(expected);
const result = await service.getById("cfg-1");
expect(prisma.agentProviderConfig.findUnique).toHaveBeenCalledWith({
where: { id: "cfg-1" },
});
expect(result).toEqual(expected);
});
it("throws NotFoundException when provider config is missing", async () => {
prisma.agentProviderConfig.findUnique.mockResolvedValue(null);
await expect(service.getById("missing")).rejects.toBeInstanceOf(NotFoundException);
});
it("creates a provider config with default credentials", async () => {
const created = {
id: "cfg-created",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "New Provider",
provider: "claude",
gatewayUrl: "https://gateway.example.com",
credentials: {},
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
};
prisma.agentProviderConfig.create.mockResolvedValue(created);
const result = await service.create({
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "New Provider",
provider: "claude",
gatewayUrl: "https://gateway.example.com",
});
expect(prisma.agentProviderConfig.create).toHaveBeenCalledWith({
data: {
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "New Provider",
provider: "claude",
gatewayUrl: "https://gateway.example.com",
credentials: {},
},
});
expect(result).toEqual(created);
});
it("updates a provider config", async () => {
prisma.agentProviderConfig.findUnique.mockResolvedValue({
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Primary",
provider: "openai",
gatewayUrl: "https://gateway.example.com",
credentials: {},
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
});
const updated = {
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Secondary",
provider: "openai",
gatewayUrl: "https://gateway2.example.com",
credentials: { apiKeyRef: "vault:new" },
isActive: false,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T19:00:00.000Z"),
};
prisma.agentProviderConfig.update.mockResolvedValue(updated);
const result = await service.update("cfg-1", {
name: "Secondary",
gatewayUrl: "https://gateway2.example.com",
credentials: { apiKeyRef: "vault:new" },
isActive: false,
});
expect(prisma.agentProviderConfig.update).toHaveBeenCalledWith({
where: { id: "cfg-1" },
data: {
name: "Secondary",
gatewayUrl: "https://gateway2.example.com",
credentials: { apiKeyRef: "vault:new" },
isActive: false,
},
});
expect(result).toEqual(updated);
});
it("throws NotFoundException when updating a missing provider config", async () => {
prisma.agentProviderConfig.findUnique.mockResolvedValue(null);
await expect(service.update("missing", { name: "Updated" })).rejects.toBeInstanceOf(
NotFoundException
);
expect(prisma.agentProviderConfig.update).not.toHaveBeenCalled();
});
it("deletes a provider config", async () => {
prisma.agentProviderConfig.findUnique.mockResolvedValue({
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Primary",
provider: "openai",
gatewayUrl: "https://gateway.example.com",
credentials: {},
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
});
const deleted = {
id: "cfg-1",
workspaceId: "8bcd7eda-a122-4d6c-adfd-b152f6f75369",
name: "Primary",
provider: "openai",
gatewayUrl: "https://gateway.example.com",
credentials: {},
isActive: true,
createdAt: new Date("2026-03-07T18:00:00.000Z"),
updatedAt: new Date("2026-03-07T18:00:00.000Z"),
};
prisma.agentProviderConfig.delete.mockResolvedValue(deleted);
const result = await service.delete("cfg-1");
expect(prisma.agentProviderConfig.delete).toHaveBeenCalledWith({
where: { id: "cfg-1" },
});
expect(result).toEqual(deleted);
});
it("throws NotFoundException when deleting a missing provider config", async () => {
prisma.agentProviderConfig.findUnique.mockResolvedValue(null);
await expect(service.delete("missing")).rejects.toBeInstanceOf(NotFoundException);
expect(prisma.agentProviderConfig.delete).not.toHaveBeenCalled();
});
});