import { beforeEach, describe, expect, it, vi } from "vitest"; import { PermissionKey, SystemRole } from "@capakraken/shared"; import { createToolContext, executeTool } from "./assistant-tools-timeline-shifts-test-helpers.js"; describe("assistant timeline project shift tools", () => { beforeEach(() => { vi.clearAllMocks(); }); it("applies timeline project shifts through the real timeline router mutation", async () => { const { listAssignmentBookings } = await import("@capakraken/application"); vi.mocked(listAssignmentBookings).mockResolvedValueOnce([]); const db = { project: { findUnique: vi.fn().mockResolvedValue({ id: "project_1", name: "Gelddruckmaschine", shortCode: "GDM", status: "ACTIVE", responsiblePerson: null, budgetCents: 100000, winProbability: 100, startDate: new Date("2026-03-16"), endDate: new Date("2026-03-20"), }), update: vi.fn().mockResolvedValue({ id: "project_1", startDate: new Date("2026-03-23"), endDate: new Date("2026-03-27"), }), }, demandRequirement: { findMany: vi.fn().mockResolvedValue([]), }, assignment: { findMany: vi.fn().mockResolvedValue([]), }, auditLog: { create: vi.fn().mockResolvedValue({}), }, $transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)), }; const ctx = createToolContext( db, [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS], SystemRole.MANAGER, ); const result = await executeTool( "apply_timeline_project_shift", JSON.stringify({ projectIdentifier: "project_1", newStartDate: "2026-03-23", newEndDate: "2026-03-27", }), ctx, ); expect(result.action).toEqual({ type: "invalidate", scope: ["allocation", "timeline", "project"] }); expect(JSON.parse(result.content)).toEqual( expect.objectContaining({ success: true, project: expect.objectContaining({ id: "project_1", startDate: "2026-03-23", endDate: "2026-03-27", }), validation: expect.objectContaining({ valid: true, }), }), ); expect(db.project.update).toHaveBeenCalledWith( expect.objectContaining({ where: { id: "project_1" }, }), ); }); it("returns a stable project-not-found error if the timeline shift target disappears mid-mutation", async () => { const { listAssignmentBookings } = await import("@capakraken/application"); vi.mocked(listAssignmentBookings).mockResolvedValueOnce([]); const db = { project: { findUnique: vi .fn() .mockResolvedValueOnce({ id: "project_1", name: "Gelddruckmaschine", shortCode: "GDM", status: "ACTIVE", responsiblePerson: null, budgetCents: 100000, winProbability: 100, startDate: new Date("2026-03-16"), endDate: new Date("2026-03-20"), }) .mockResolvedValueOnce(null), }, demandRequirement: { findMany: vi.fn().mockResolvedValue([]), }, assignment: { findMany: vi.fn().mockResolvedValue([]), }, }; const ctx = createToolContext( db, [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS], SystemRole.MANAGER, ); const result = await executeTool( "apply_timeline_project_shift", JSON.stringify({ projectIdentifier: "project_1", newStartDate: "2026-03-23", newEndDate: "2026-03-27", }), ctx, ); expect(result.action).toBeUndefined(); expect(JSON.parse(result.content)).toEqual({ error: "Project not found with the given criteria.", }); }); });