test(api): cover assistant allocation reads

This commit is contained in:
2026-04-01 00:31:51 +02:00
parent 53158dc60d
commit 3a82a52897
@@ -0,0 +1,244 @@
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(),
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 allocation listing through the allocation router path", async () => {
const db = {
systemSettings: {
findUnique: vi.fn().mockResolvedValue({
anonymizationEnabled: false,
anonymizationDomain: null,
anonymizationSeed: null,
anonymizationMode: null,
anonymizationAliases: null,
}),
},
demandRequirement: {
findMany: vi.fn().mockResolvedValue([
{
id: "demand_1",
projectId: "project_1",
startDate: new Date("2026-04-01T00:00:00.000Z"),
endDate: new Date("2026-04-30T00:00:00.000Z"),
hoursPerDay: 8,
percentage: 100,
role: "TD",
roleId: null,
headcount: 1,
status: "OPEN",
metadata: null,
createdAt: new Date("2026-03-20T00:00:00.000Z"),
updatedAt: new Date("2026-03-20T00:00:00.000Z"),
project: {
id: "project_1",
name: "Gelddruckmaschine",
shortCode: "GDM",
status: "ACTIVE",
endDate: new Date("2026-04-30T00:00:00.000Z"),
},
roleEntity: null,
assignments: [],
},
]),
},
assignment: {
findMany: vi.fn().mockResolvedValue([
{
id: "assign_1",
demandRequirementId: null,
resourceId: "res_1",
projectId: "project_1",
startDate: new Date("2026-04-01T00:00:00.000Z"),
endDate: new Date("2026-04-10T00:00:00.000Z"),
hoursPerDay: 6,
percentage: 75,
role: "Pipeline TD",
roleId: null,
dailyCostCents: 12_000,
status: "ACTIVE",
metadata: null,
createdAt: new Date("2026-03-21T00:00:00.000Z"),
updatedAt: new Date("2026-03-21T00:00:00.000Z"),
resource: {
id: "res_1",
displayName: "Bruce Banner",
eid: "EMP-001",
lcrCents: 8_500,
},
project: {
id: "project_1",
name: "Gelddruckmaschine",
shortCode: "GDM",
status: "ACTIVE",
endDate: new Date("2026-04-30T00:00:00.000Z"),
},
roleEntity: null,
demandRequirement: null,
},
]),
},
};
const ctx = createToolContext(db, {
userRole: SystemRole.CONTROLLER,
permissions: [PermissionKey.VIEW_PLANNING],
});
const result = await executeTool(
"list_allocations",
JSON.stringify({
projectId: "project_1",
resourceName: "Bruce",
projectCode: "GDM",
status: "ACTIVE",
limit: 10,
}),
ctx,
);
expect(db.demandRequirement.findMany).toHaveBeenCalledWith({
where: {
projectId: "project_1",
status: "ACTIVE",
},
include: {
project: {
select: {
id: true,
name: true,
shortCode: true,
status: true,
endDate: true,
},
},
roleEntity: {
select: { id: true, name: true, color: true },
},
assignments: {
include: {
resource: {
select: {
id: true,
displayName: true,
eid: true,
lcrCents: true,
chapter: true,
},
},
project: {
select: {
id: true,
name: true,
shortCode: true,
status: true,
endDate: true,
},
},
roleEntity: {
select: { id: true, name: true, color: true },
},
},
},
},
orderBy: { startDate: "asc" },
});
expect(db.assignment.findMany).toHaveBeenCalledWith({
where: {
projectId: "project_1",
status: "ACTIVE",
},
include: {
resource: {
select: {
id: true,
displayName: true,
eid: true,
lcrCents: true,
chapter: true,
},
},
project: {
select: {
id: true,
name: true,
shortCode: true,
status: true,
endDate: true,
},
},
roleEntity: {
select: { id: true, name: true, color: true },
},
demandRequirement: {
select: {
id: true,
projectId: true,
startDate: true,
endDate: true,
hoursPerDay: true,
percentage: true,
role: true,
roleId: true,
headcount: true,
status: true,
},
},
},
orderBy: { startDate: "asc" },
});
expect(JSON.parse(result.content)).toEqual([
{
id: "assign_1",
resource: "Bruce Banner",
resourceEid: "EMP-001",
project: "Gelddruckmaschine",
projectCode: "GDM",
role: "Pipeline TD",
status: "ACTIVE",
hoursPerDay: 6,
dailyCost: "120,00 EUR",
start: "2026-04-01",
end: "2026-04-10",
},
]);
});
});