From 276751c4caab35bcac06c6cfc53fd972a8b20836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Wed, 1 Apr 2026 00:37:45 +0200 Subject: [PATCH] test(api): cover assistant estimate draft errors --- ...istant-tools-estimate-draft-errors.test.ts | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 packages/api/src/__tests__/assistant-tools-estimate-draft-errors.test.ts diff --git a/packages/api/src/__tests__/assistant-tools-estimate-draft-errors.test.ts b/packages/api/src/__tests__/assistant-tools-estimate-draft-errors.test.ts new file mode 100644 index 0000000..c25ffba --- /dev/null +++ b/packages/api/src/__tests__/assistant-tools-estimate-draft-errors.test.ts @@ -0,0 +1,163 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { PermissionKey, SystemRole } from "@capakraken/shared"; + +vi.mock("@capakraken/application", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + approveEstimateVersion: vi.fn(), + cloneEstimate: vi.fn(), + createEstimateExport: vi.fn(), + createEstimatePlanningHandoff: vi.fn(), + createEstimateRevision: vi.fn(), + getDashboardBudgetForecast: vi.fn().mockResolvedValue([]), + getDashboardPeakTimes: vi.fn().mockResolvedValue([]), + getEstimateById: vi.fn(), + listAssignmentBookings: vi.fn().mockResolvedValue([]), + submitEstimateVersion: vi.fn(), + updateEstimateDraft: vi.fn(), + }; +}); + +import { updateEstimateDraft } from "@capakraken/application"; + +import { executeTool } from "../router/assistant-tools.js"; +import { + createToolContext, + resetEstimateToolMocks, +} from "./assistant-tools-estimate-test-helpers.js"; + +describe("assistant estimate draft update errors", () => { + beforeEach(() => { + resetEstimateToolMocks(); + }); + + it("returns stable assistant errors for update_estimate_draft mutations", async () => { + const basePayload = { + baseCurrency: "EUR", + assumptions: [], + scopeItems: [], + demandLines: [], + resourceSnapshots: [], + metrics: [], + }; + const cases = [ + { + payload: { id: "est_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => vi.mocked(updateEstimateDraft).mockRejectedValueOnce(new Error("Estimate not found")), + expected: "Estimate not found with the given criteria.", + }, + { + payload: { id: "est_locked", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => vi.mocked(updateEstimateDraft).mockRejectedValueOnce(new Error("Estimate has no working version")), + expected: "Estimate has no working version.", + }, + { + payload: { id: "est_scope_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => + vi.mocked(updateEstimateDraft).mockRejectedValueOnce( + Object.assign(new Error("Foreign key constraint failed"), { + code: "P2003", + meta: { field_name: "EstimateScopeItem_scopeItemId_fkey" }, + }), + ), + expected: "Estimate scope item not found with the given criteria.", + }, + { + payload: { id: "est_project_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => + vi.mocked(updateEstimateDraft).mockRejectedValueOnce( + Object.assign(new Error("Foreign key constraint failed"), { + code: "P2003", + meta: { field_name: "Estimate_projectId_fkey" }, + }), + ), + expected: "Project not found with the given criteria.", + }, + { + payload: { id: "est_role_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => + vi.mocked(updateEstimateDraft).mockRejectedValueOnce( + Object.assign(new Error("Foreign key constraint failed"), { + code: "P2003", + meta: { field_name: "EstimateDemandLine_roleId_fkey" }, + }), + ), + expected: "Role not found with the given criteria.", + }, + { + payload: { id: "est_resource_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => + vi.mocked(updateEstimateDraft).mockRejectedValueOnce( + Object.assign(new Error("Foreign key constraint failed"), { + code: "P2003", + meta: { field_name: "EstimateDemandLine_resourceId_fkey" }, + }), + ), + expected: "Resource not found with the given criteria.", + }, + { + payload: { id: "est_reference_missing", ...basePayload }, + db: { + estimate: { + findUnique: vi.fn().mockResolvedValue({ projectId: null }), + }, + }, + setup: () => + vi.mocked(updateEstimateDraft).mockRejectedValueOnce( + Object.assign(new Error("Foreign key constraint failed"), { + code: "P2003", + meta: { field_name: "EstimateVersion_estimateId_fkey" }, + }), + ), + expected: "One of the referenced project, role, resource, or scope items no longer exists.", + }, + ] as const; + + for (const testCase of cases) { + testCase.setup(); + const ctx = createToolContext(testCase.db, { + userRole: SystemRole.MANAGER, + permissions: [PermissionKey.MANAGE_PROJECTS], + }); + + const result = await executeTool( + "update_estimate_draft", + JSON.stringify(testCase.payload), + ctx, + ); + + expect(JSON.parse(result.content)).toEqual({ error: testCase.expected }); + } + }); +});