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 { executeTool } from "../router/assistant-tools.js"; import { createToolContext, resetEstimateToolMocks, } from "./assistant-tools-estimate-test-helpers.js"; describe("assistant estimate version snapshot tools", () => { beforeEach(() => { resetEstimateToolMocks(); }); it("reads estimate version snapshots through the real estimate router, requires viewCosts, and rejects plain users", async () => { const db = { estimate: { findUnique: vi.fn().mockResolvedValue({ id: "est_1", name: "North Cluster Estimate", status: "APPROVED", baseCurrency: "EUR", versions: [ { id: "ver_4", versionNumber: 4, label: "Rev 4", status: "APPROVED", notes: "Latest", lockedAt: new Date("2026-03-29T00:00:00.000Z"), createdAt: new Date("2026-03-28T00:00:00.000Z"), updatedAt: new Date("2026-03-29T00:00:00.000Z"), assumptions: [ { id: "ass_1", category: "DELIVERY", key: "onsite", label: "Onsite support" }, ], scopeItems: [ { id: "scope_1", scopeType: "EPIC", sequenceNo: 1, name: "Pipeline" }, ], demandLines: [ { id: "dl_1", name: "Modeling", chapter: "3D", hours: 40, costTotalCents: 400000, priceTotalCents: 600000, currency: "EUR", }, ], resourceSnapshots: [ { id: "snap_1", displayName: "Alice", chapter: "3D", currency: "EUR", lcrCents: 10000, ucrCents: 15000, }, ], exports: [ { id: "exp_1", format: "XLSX", fileName: "estimate.xlsx", createdAt: new Date("2026-03-29T10:00:00.000Z"), }, ], }, ], }), }, }; const controllerCtx = createToolContext(db, { userRole: SystemRole.CONTROLLER, permissions: [PermissionKey.VIEW_COSTS], }); const controllerWithoutCostsCtx = createToolContext(db, { userRole: SystemRole.CONTROLLER, permissions: [], }); const userCtx = createToolContext({}, { userRole: SystemRole.USER }); const successResult = await executeTool( "get_estimate_version_snapshot", JSON.stringify({ estimateId: "est_1", versionId: "ver_4" }), controllerCtx, ); const missingPermissionResult = await executeTool( "get_estimate_version_snapshot", JSON.stringify({ estimateId: "est_1", versionId: "ver_4" }), controllerWithoutCostsCtx, ); const deniedResult = await executeTool( "get_estimate_version_snapshot", JSON.stringify({ estimateId: "est_1", versionId: "ver_4" }), userCtx, ); expect(db.estimate.findUnique).toHaveBeenCalledWith({ where: { id: "est_1" }, select: expect.objectContaining({ id: true, versions: expect.objectContaining({ where: { id: "ver_4" }, }), }), }); expect(JSON.parse(successResult.content)).toEqual( expect.objectContaining({ estimate: expect.objectContaining({ id: "est_1", baseCurrency: "EUR", }), version: expect.objectContaining({ id: "ver_4", versionNumber: 4, }), totals: expect.objectContaining({ hours: 40, costTotalCents: 400000, priceTotalCents: 600000, }), chapterBreakdown: [ expect.objectContaining({ chapter: "3D", lineCount: 1, }), ], }), ); expect(JSON.parse(missingPermissionResult.content)).toEqual( expect.objectContaining({ error: expect.stringContaining(PermissionKey.VIEW_COSTS), }), ); expect(JSON.parse(deniedResult.content)).toEqual( expect.objectContaining({ error: "You do not have permission to perform this action.", }), ); }); });