test(api): cover assistant estimate reads

This commit is contained in:
2026-04-01 00:37:38 +02:00
parent c510eeae37
commit 80c31cc53f
5 changed files with 487 additions and 0 deletions
@@ -0,0 +1,160 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { PermissionKey, SystemRole } from "@capakraken/shared";
vi.mock("@capakraken/application", async (importOriginal) => {
const actual = await importOriginal<typeof import("@capakraken/application")>();
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.",
}),
);
});
});