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, getDashboardBudgetForecast: vi.fn().mockResolvedValue([]), getDashboardPeakTimes: vi.fn().mockResolvedValue([]), listAssignmentBookings: vi.fn().mockResolvedValue([]), }; }); vi.mock("../sse/event-bus.js", () => ({ emitAllocationCreated: vi.fn(), emitAllocationDeleted: vi.fn(), emitAllocationUpdated: vi.fn(), emitProjectShifted: vi.fn(), })); vi.mock("../lib/budget-alerts.js", () => ({ checkBudgetThresholds: vi.fn(), })); vi.mock("../lib/cache.js", () => ({ invalidateDashboardCache: vi.fn(), })); import { executeTool } from "../router/assistant-tools.js"; import { createToolContext } from "./assistant-tools-advanced-timeline-test-helpers.js"; import { baseAvailability, buildBaseAssignment, } from "./assistant-tools-timeline-allocation-mutation-test-helpers.js"; describe("assistant timeline inline allocation update error tools", () => { beforeEach(() => { vi.clearAllMocks(); }); it("returns a stable validation error for inline timeline mutation date ranges", async () => { const ctx = createToolContext( { allocation: { findUnique: vi.fn().mockResolvedValue(null), }, demandRequirement: { findUnique: vi.fn().mockResolvedValue(null), }, assignment: { findUnique: vi.fn().mockResolvedValue(buildBaseAssignment()), }, resource: { findUnique: vi.fn().mockResolvedValue({ id: "resource_1", lcrCents: 5000, availability: baseAvailability, }), }, }, [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS], SystemRole.MANAGER, ); const result = await executeTool( "update_timeline_allocation_inline", JSON.stringify({ allocationId: "assignment_1", startDate: "2026-03-20", endDate: "2026-03-16", }), ctx, ); expect(JSON.parse(result.content)).toEqual({ error: "End date must be after start date", }); }); it("returns a stable allocation-not-found error for inline timeline updates", async () => { const db = { allocation: { findUnique: vi.fn().mockResolvedValue(null), }, demandRequirement: { findUnique: vi.fn().mockResolvedValue(null), }, assignment: { findUnique: vi.fn().mockResolvedValue(null), }, }; const ctx = createToolContext( db, [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS], SystemRole.MANAGER, ); const result = await executeTool( "update_timeline_allocation_inline", JSON.stringify({ allocationId: "assignment_missing", hoursPerDay: 6, }), ctx, ); expect(result.action).toBeUndefined(); expect(JSON.parse(result.content)).toEqual({ error: "Allocation not found with the given criteria.", }); }); it("returns stable allocation-not-found errors when timeline allocation persistence loses the row", async () => { const missingDuringUpdate = { code: "P2025", message: "Record to update not found", meta: { modelName: "Assignment" }, }; const updateInlineCtx = createToolContext( { allocation: { findUnique: vi.fn().mockResolvedValue(null), }, demandRequirement: { findUnique: vi.fn().mockResolvedValue(null), }, assignment: { findUnique: vi.fn().mockResolvedValue(buildBaseAssignment()), }, resource: { findUnique: vi.fn().mockResolvedValue({ id: "resource_1", lcrCents: 5000, availability: baseAvailability, }), }, auditLog: { create: vi.fn().mockResolvedValue({}), }, vacation: { findMany: vi.fn().mockResolvedValue([]), }, $transaction: vi.fn(async () => { throw missingDuringUpdate; }), }, [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS], SystemRole.MANAGER, ); const updateInlineResult = await executeTool( "update_timeline_allocation_inline", JSON.stringify({ allocationId: "assignment_1", hoursPerDay: 6, }), updateInlineCtx, ); expect(JSON.parse(updateInlineResult.content)).toEqual({ error: "Allocation not found with the given criteria.", }); }); });