import { beforeEach, describe, expect, it, vi } from "vitest"; import { VacationType } from "@capakraken/db"; import { SystemRole } from "@capakraken/shared"; vi.mock("@capakraken/application", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, approveEstimateVersion: vi.fn(), cloneEstimate: vi.fn(), commitDispoImportBatch: vi.fn(), countPlanningEntries: vi.fn().mockResolvedValue({ countsByRoleId: new Map() }), createEstimateExport: vi.fn(), createEstimatePlanningHandoff: vi.fn(), createEstimateRevision: vi.fn(), assessDispoImportReadiness: vi.fn(), loadResourceDailyAvailabilityContexts: vi.fn().mockResolvedValue(new Map()), getDashboardDemand: vi.fn().mockResolvedValue([]), getDashboardBudgetForecast: vi.fn().mockResolvedValue([]), getDashboardOverview: vi.fn(), getDashboardSkillGapSummary: vi.fn().mockResolvedValue({ roleGaps: [], totalOpenPositions: 0, skillSupplyTop10: [], resourcesByRole: [], }), getDashboardProjectHealth: vi.fn().mockResolvedValue([]), getDashboardPeakTimes: vi.fn().mockResolvedValue([]), getDashboardTopValueResources: vi.fn().mockResolvedValue([]), getEstimateById: vi.fn(), listAssignmentBookings: vi.fn().mockResolvedValue([]), stageDispoImportBatch: vi.fn(), submitEstimateVersion: vi.fn(), updateEstimateDraft: vi.fn(), }; }); import { executeTool } from "../router/assistant-tools.js"; import { createToolContext } from "./assistant-tools-planning-read-test-helpers.js"; describe("assistant planning allocation and vacation read tools", () => { beforeEach(() => { vi.clearAllMocks(); }); it("routes upcoming vacation reads through the vacation router path and post-filters by chapter", async () => { vi.useFakeTimers(); vi.setSystemTime(new Date("2026-03-01T00:00:00.000Z")); try { const db = { vacation: { findMany: vi.fn().mockResolvedValue([ { id: "vac_1", resourceId: "res_1", status: "APPROVED", type: VacationType.ANNUAL, startDate: new Date("2026-03-05T00:00:00.000Z"), endDate: new Date("2026-03-06T00:00:00.000Z"), isHalfDay: false, halfDayPart: null, resource: { id: "res_1", displayName: "Bruce Banner", eid: "EMP-001", lcrCents: 8_000, chapter: "Delivery", }, requestedBy: null, approvedBy: null, }, { id: "vac_2", resourceId: "res_2", status: "APPROVED", type: VacationType.ANNUAL, startDate: new Date("2026-03-07T00:00:00.000Z"), endDate: new Date("2026-03-07T00:00:00.000Z"), isHalfDay: true, halfDayPart: "MORNING", resource: { id: "res_2", displayName: "Tony Stark", eid: "EMP-002", lcrCents: 9_000, chapter: "Finance", }, requestedBy: null, approvedBy: null, }, ]), }, }; const ctx = createToolContext(db, { userRole: SystemRole.MANAGER }); const result = await executeTool( "list_vacations_upcoming", JSON.stringify({ chapter: "Delivery", daysAhead: 14, limit: 10 }), ctx, ); expect(db.vacation.findMany).toHaveBeenCalledWith({ where: { status: "APPROVED", endDate: { gte: new Date("2026-03-01T00:00:00.000Z") }, startDate: { lte: new Date("2026-03-15T00:00:00.000Z") }, }, include: { resource: { select: { id: true, displayName: true, eid: true, lcrCents: true, chapter: true, }, }, requestedBy: { select: { id: true, name: true, email: true } }, approvedBy: { select: { id: true, name: true, email: true } }, }, orderBy: { startDate: "asc" }, take: 10, }); expect(JSON.parse(result.content)).toEqual([ { resource: "Bruce Banner", eid: "EMP-001", chapter: "Delivery", type: VacationType.ANNUAL, start: "2026-03-05", end: "2026-03-06", isHalfDay: false, halfDayPart: null, }, ]); } finally { vi.useRealTimers(); } }); });