test(api): cover assistant master data rate lookup

This commit is contained in:
2026-04-01 00:41:40 +02:00
parent 43c4ad37f3
commit 740ef0ecdb
@@ -0,0 +1,139 @@
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,
countPlanningEntries: vi.fn().mockResolvedValue({ countsByRoleId: new Map() }),
getDashboardBudgetForecast: vi.fn().mockResolvedValue([]),
getDashboardPeakTimes: vi.fn().mockResolvedValue([]),
listAssignmentBookings: vi.fn().mockResolvedValue([]),
};
});
import { countPlanningEntries } from "@capakraken/application";
import { executeTool } from "../router/assistant-tools.js";
import { createToolContext } from "./assistant-tools-master-data-read-test-helpers.js";
describe("assistant master data rate lookup tools", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(countPlanningEntries).mockResolvedValue({ countsByRoleId: new Map() });
});
it("routes rate lookup reads through the rate-card router path", async () => {
const db = {
rateCard: {
findMany: vi.fn().mockResolvedValue([
{
id: "rc_client",
name: "Client 2026",
client: { id: "client_1", name: "Acme Mobility" },
lines: [
{
id: "line_best",
chapter: "Delivery",
seniority: "Senior",
costRateCents: 12_000,
billRateCents: 18_000,
role: { id: "role_1", name: "Pipeline TD" },
},
],
},
{
id: "rc_default",
name: "Default 2026",
client: null,
lines: [
{
id: "line_alt",
chapter: "Delivery",
seniority: "Senior",
costRateCents: 11_000,
billRateCents: 17_000,
role: { id: "role_1", name: "Pipeline TD" },
},
],
},
]),
},
role: {
findFirst: vi.fn().mockResolvedValue({ id: "role_1" }),
},
};
const ctx = createToolContext(db, {
userRole: SystemRole.CONTROLLER,
permissions: [PermissionKey.VIEW_COSTS],
});
const result = await executeTool(
"lookup_rate",
JSON.stringify({
clientId: "client_1",
chapter: "Delivery",
roleName: "Pipeline",
seniority: "Senior",
}),
ctx,
);
expect(db.rateCard.findMany).toHaveBeenCalledWith({
where: {
isActive: true,
OR: [{ clientId: "client_1" }, { clientId: null }],
},
include: {
lines: {
select: {
id: true,
chapter: true,
seniority: true,
costRateCents: true,
billRateCents: true,
role: { select: { id: true, name: true } },
},
},
client: { select: { id: true, name: true } },
},
orderBy: [{ effectiveFrom: "desc" }],
});
expect(db.role.findFirst).toHaveBeenCalledWith({
where: { name: { contains: "Pipeline", mode: "insensitive" } },
select: { id: true },
});
expect(JSON.parse(result.content)).toEqual({
bestMatch: {
rateCardName: "Client 2026",
clientId: "client_1",
clientName: "Acme Mobility",
lineId: "line_best",
chapter: "Delivery",
seniority: "Senior",
roleName: "Pipeline TD",
costRateCents: 12000,
billRateCents: 18000,
score: 10,
costRate: "120,00 EUR",
billRate: "180,00 EUR",
},
alternatives: [
{
rateCardName: "Default 2026",
clientId: null,
clientName: null,
lineId: "line_alt",
chapter: "Delivery",
seniority: "Senior",
roleName: "Pipeline TD",
costRateCents: 11000,
billRateCents: 17000,
score: 7,
costRate: "110,00 EUR",
billRate: "170,00 EUR",
},
],
totalCandidates: 2,
});
});
});