test(api): harden assistant tool error handling

This commit is contained in:
2026-03-30 11:51:59 +02:00
parent 4ce8577824
commit 7aa32f8a5c
8 changed files with 7898 additions and 381 deletions
@@ -320,6 +320,100 @@ describe("assistant holiday tools", () => {
);
});
it("returns stable assistant errors for holiday calendar and entry mutations", async () => {
const cases = [
{
name: "invalid holiday calendar scope",
toolName: "create_holiday_calendar",
db: {
country: {
findUnique: vi.fn().mockResolvedValue({ id: "country_de", code: "DE", name: "Deutschland" }),
},
holidayCalendar: {
findFirst: vi.fn().mockResolvedValue(null),
},
},
payload: {
name: "Ungueltiger Kalender",
scopeType: "STATE",
countryId: "country_de",
},
expected: "Holiday calendar scope is invalid.",
},
{
name: "duplicate holiday calendar scope",
toolName: "create_holiday_calendar",
db: {
country: {
findUnique: vi.fn().mockResolvedValue({ id: "country_de", code: "DE", name: "Deutschland" }),
},
holidayCalendar: {
findFirst: vi.fn().mockResolvedValue({ id: "cal_existing" }),
},
},
payload: {
name: "Bayern Feiertage",
scopeType: "STATE",
countryId: "country_de",
stateCode: "BY",
},
expected: "A holiday calendar for this scope already exists.",
},
{
name: "holiday calendar not found on delete",
toolName: "delete_holiday_calendar",
db: {
holidayCalendar: {
findUnique: vi.fn().mockResolvedValue(null),
},
},
payload: { id: "cal_missing" },
expected: "Holiday calendar not found with the given criteria.",
},
{
name: "holiday calendar entry not found on delete",
toolName: "delete_holiday_calendar_entry",
db: {
holidayCalendarEntry: {
findUnique: vi.fn().mockResolvedValue(null),
},
},
payload: { id: "entry_missing" },
expected: "Holiday calendar entry not found with the given criteria.",
},
{
name: "duplicate holiday calendar entry date",
toolName: "create_holiday_calendar_entry",
db: {
holidayCalendar: {
findUnique: vi.fn().mockResolvedValue({ id: "cal_by", name: "Bayern Feiertage" }),
},
holidayCalendarEntry: {
findFirst: vi.fn().mockResolvedValue({ id: "entry_existing" }),
},
},
payload: {
holidayCalendarId: "cal_by",
date: "2026-01-06",
name: "Heilige Drei Koenige",
},
expected: "A holiday entry for this calendar and date already exists.",
},
] as const;
for (const testCase of cases) {
const result = await executeTool(
testCase.toolName,
JSON.stringify(testCase.payload),
createToolContext(testCase.db),
);
expect(JSON.parse(result.content)).toEqual({
error: testCase.expected,
});
}
});
it("calculates chargeability with regional holidays excluded from booked and available hours", async () => {
const resourceRecord = {
id: "res_1",
@@ -763,6 +857,37 @@ describe("assistant holiday tools", () => {
);
});
it("returns a stable assistant error when staffing suggestions receive an invalid optional start date", async () => {
const db = {
project: {
findUnique: vi
.fn()
.mockResolvedValueOnce(null)
.mockResolvedValueOnce({
id: "project_1",
name: "Holiday Project",
shortCode: "HP",
status: "ACTIVE",
responsiblePerson: null,
startDate: new Date("2026-01-05T00:00:00.000Z"),
endDate: new Date("2026-01-16T00:00:00.000Z"),
}),
findFirst: vi.fn().mockResolvedValue(null),
},
};
const ctx = createToolContext(db);
const result = await executeTool(
"get_staffing_suggestions",
JSON.stringify({ projectId: "project_1", startDate: "2026-99-01" }),
ctx,
);
expect(JSON.parse(result.content)).toEqual({
error: "Invalid startDate: 2026-99-01",
});
});
it("uses holiday-aware assignment hours for assistant shoring ratio", async () => {
const db = {
project: {