import { beforeEach, describe, expect, it, vi } from "vitest"; import { PermissionKey, SystemRole } from "@capakraken/shared"; import { TRPCError } from "@trpc/server"; import { createToolContext, executeTool, } from "./assistant-tools-project-admin-create-test-helpers.js"; describe("assistant project admin create tools - blueprint errors", () => { beforeEach(() => { vi.clearAllMocks(); }); it("returns a stable assistant error when the blueprint cannot be resolved", async () => { const projectCreate = vi.fn(); const ctx = createToolContext( { resource: { findFirst: vi.fn().mockResolvedValue({ displayName: "Peter Parker", }), findMany: vi.fn().mockResolvedValue([]), }, project: { findUnique: vi.fn().mockResolvedValue(null), create: projectCreate, }, blueprint: { findUnique: vi.fn().mockResolvedValue(null), findFirst: vi.fn().mockResolvedValue(null), }, client: { findUnique: vi.fn().mockResolvedValue(null), findFirst: vi.fn().mockResolvedValue(null), }, auditLog: { create: vi.fn(), }, }, { userRole: SystemRole.ADMIN, permissions: [PermissionKey.MANAGE_PROJECTS], }, ); const result = await executeTool( "create_project", JSON.stringify({ shortCode: "PROJ-404", name: "Missing Blueprint Project", orderType: "CHARGEABLE", budgetCents: 150000, startDate: "2026-05-01", endDate: "2026-06-30", responsiblePerson: "Peter Parker", blueprintName: "Missing Blueprint", }), ctx, ); expect(JSON.parse(result.content)).toEqual({ error: 'Blueprint not found: "Missing Blueprint"', }); expect(projectCreate).not.toHaveBeenCalled(); }); it("returns a generic assistant error when blueprint resolution fails internally during project creation", async () => { const projectCreate = vi.fn(); const ctx = createToolContext( { resource: { findFirst: vi.fn().mockResolvedValue({ displayName: "Peter Parker", }), findMany: vi.fn().mockResolvedValue([]), }, project: { findUnique: vi.fn().mockResolvedValue(null), create: projectCreate, }, blueprint: { findUnique: vi.fn().mockRejectedValue( new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "blueprint resolver connection exhausted", }), ), }, client: { findUnique: vi.fn().mockResolvedValue(null), findFirst: vi.fn().mockResolvedValue(null), }, auditLog: { create: vi.fn(), }, }, { userRole: SystemRole.ADMIN, permissions: [PermissionKey.MANAGE_PROJECTS], }, ); const result = await executeTool( "create_project", JSON.stringify({ shortCode: "PROJ-500", name: "Blueprint Failure Project", orderType: "CHARGEABLE", budgetCents: 150000, startDate: "2026-05-01", endDate: "2026-06-30", responsiblePerson: "Peter Parker", blueprintName: "Consulting Blueprint", }), ctx, ); expect(JSON.parse(result.content)).toEqual({ error: "The tool could not complete due to an internal error.", }); expect(projectCreate).not.toHaveBeenCalled(); }); it("returns a stable assistant error when the project blueprint disappears before creation", async () => { const projectCreate = vi.fn(); const blueprintFindUnique = vi.fn() .mockResolvedValueOnce({ id: "bp_1", name: "Consulting Blueprint", target: "PROJECT", isActive: true, }) .mockResolvedValueOnce(null); const ctx = createToolContext( { resource: { findFirst: vi.fn().mockResolvedValue({ displayName: "Peter Parker", }), findMany: vi.fn().mockResolvedValue([]), }, project: { findUnique: vi.fn().mockResolvedValue(null), create: projectCreate, }, blueprint: { findUnique: blueprintFindUnique, findFirst: vi.fn().mockResolvedValue(null), }, }, { userRole: SystemRole.ADMIN, permissions: [PermissionKey.MANAGE_PROJECTS], }, ); const result = await executeTool( "create_project", JSON.stringify({ shortCode: "PROJ-BP", name: "Blueprint Race Project", orderType: "CHARGEABLE", budgetCents: 150000, startDate: "2026-05-01", endDate: "2026-06-30", responsiblePerson: "Peter Parker", blueprintName: "Consulting Blueprint", }), ctx, ); expect(JSON.parse(result.content)).toEqual({ error: "Blueprint not found with the given criteria.", }); expect(projectCreate).not.toHaveBeenCalled(); }); });