test(api): widen resource capacity edge coverage

This commit is contained in:
2026-04-01 07:52:40 +02:00
parent 6370c8acef
commit 7277e60691
@@ -261,6 +261,118 @@ describe("resource router", () => {
});
});
it("returns an empty utilization result when no active resources match the chapter filter", async () => {
const db = {
resource: {
findMany: vi.fn().mockResolvedValue([]),
},
};
vi.mocked(listAssignmentBookings).mockResolvedValue([]);
const caller = createControllerCaller(db);
const result = await caller.listWithUtilization({
chapter: "Rigging",
startDate: "2026-03-01T00:00:00.000Z",
endDate: "2026-03-31T00:00:00.000Z",
});
expect(result).toEqual([]);
expect(db.resource.findMany).toHaveBeenCalledWith(expect.objectContaining({
where: {
isActive: true,
chapter: "Rigging",
},
take: 100,
orderBy: { displayName: "asc" },
}));
expect(listAssignmentBookings).toHaveBeenCalledWith(db, {
startDate: new Date("2026-03-01T00:00:00.000Z"),
endDate: new Date("2026-03-31T00:00:00.000Z"),
resourceIds: [],
});
});
it("ignores orphaned utilization bookings without a resourceId", async () => {
const resource = {
id: "resource_1",
eid: "E-001",
displayName: "Alice",
email: "alice@example.com",
chapter: "CGI",
lcrCents: 5000,
ucrCents: 9000,
currency: "EUR",
chargeabilityTarget: 80,
availability: {
monday: 8,
tuesday: 8,
wednesday: 8,
thursday: 8,
friday: 8,
},
skills: [],
dynamicFields: {},
blueprintId: null,
isActive: true,
createdAt: new Date("2026-03-01"),
updatedAt: new Date("2026-03-01"),
roleId: null,
portfolioUrl: null,
postalCode: null,
federalState: null,
valueScore: null,
valueScoreBreakdown: null,
valueScoreUpdatedAt: null,
userId: null,
countryId: "country_de",
metroCityId: null,
country: { code: "DE" },
metroCity: null,
};
const db = {
resource: {
findMany: vi.fn().mockResolvedValue([resource]),
},
};
vi.mocked(listAssignmentBookings).mockResolvedValue([
{
id: "assignment_orphaned",
projectId: "project_1",
resourceId: null,
startDate: new Date("2026-03-02T00:00:00.000Z"),
endDate: new Date("2026-03-06T00:00:00.000Z"),
hoursPerDay: 8,
dailyCostCents: 0,
status: "CONFIRMED",
project: {
id: "project_1",
name: "Project 1",
shortCode: "P1",
status: "ACTIVE",
orderType: "CLIENT",
clientId: null,
dynamicFields: null,
},
resource: null,
},
] satisfies Awaited<ReturnType<typeof listAssignmentBookings>>);
const caller = createControllerCaller(db);
const result = await caller.listWithUtilization({
startDate: "2026-03-02T00:00:00.000Z",
endDate: "2026-03-08T00:00:00.000Z",
});
expect(result[0]).toMatchObject({
id: "resource_1",
bookingCount: 0,
bookedHours: 0,
utilizationPercent: 0,
});
});
it("shifts marketplace availability when a local holiday blocks today", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-01-06T10:00:00.000Z"));
@@ -581,6 +693,190 @@ describe("resource router", () => {
}
});
it("returns zero chargeability when a resource has no working availability", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-03-15T12:00:00.000Z"));
try {
const db = {
resource: {
findMany: vi.fn().mockResolvedValue([
{
id: "resource_zero",
eid: "E-000",
displayName: "No Capacity",
chapter: "CGI",
chargeabilityTarget: 80,
availability: {
monday: 0,
tuesday: 0,
wednesday: 0,
thursday: 0,
friday: 0,
saturday: 0,
sunday: 0,
},
countryId: "country_de",
federalState: null,
metroCityId: null,
country: { code: "DE" },
metroCity: null,
},
]),
},
};
vi.mocked(listAssignmentBookings).mockResolvedValue([
{
id: "assignment_zero",
projectId: "project_1",
resourceId: "resource_zero",
startDate: new Date("2026-03-02T00:00:00.000Z"),
endDate: new Date("2026-03-06T00:00:00.000Z"),
hoursPerDay: 8,
dailyCostCents: 0,
status: "CONFIRMED",
project: {
id: "project_1",
name: "Project 1",
shortCode: "P1",
status: "ACTIVE",
orderType: "CLIENT",
dynamicFields: null,
},
resource: { id: "resource_zero", displayName: "No Capacity", chapter: "CGI" },
},
]);
const caller = createControllerCaller(db);
const result = await caller.getChargeabilityStats({});
expect(result[0]).toMatchObject({
id: "resource_zero",
actualChargeability: 0,
expectedChargeability: 0,
availableHours: 0,
});
} finally {
vi.useRealTimers();
}
});
it("returns an empty chargeability stats result when no active resources match", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-03-15T12:00:00.000Z"));
try {
const db = {
resource: {
findMany: vi.fn().mockResolvedValue([]),
},
};
vi.mocked(listAssignmentBookings).mockResolvedValue([]);
const caller = createControllerCaller(db);
const result = await caller.getChargeabilityStats({ resourceId: "missing_resource" });
expect(result).toEqual([]);
expect(db.resource.findMany).toHaveBeenCalledWith({
where: {
isActive: true,
id: "missing_resource",
},
select: {
id: true,
eid: true,
displayName: true,
chapter: true,
chargeabilityTarget: true,
availability: true,
countryId: true,
federalState: true,
metroCityId: true,
country: { select: { code: true } },
metroCity: { select: { name: true } },
},
});
expect(listAssignmentBookings).toHaveBeenCalledWith(db, expect.objectContaining({
resourceIds: [],
}));
const [, bookingQuery] = vi.mocked(listAssignmentBookings).mock.calls.at(-1)!;
expect(bookingQuery.startDate).toEqual(new Date(2026, 2, 1));
expect(bookingQuery.endDate).toEqual(new Date(2026, 3, 0));
} finally {
vi.useRealTimers();
}
});
it("passes the explicit resource filter through to chargeability stats reads", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-03-15T12:00:00.000Z"));
try {
const db = {
resource: {
findMany: vi.fn().mockResolvedValue([
{
id: "resource_target",
eid: "E-TARGET",
displayName: "Target",
chapter: "CGI",
chargeabilityTarget: 80,
availability: {
monday: 8,
tuesday: 8,
wednesday: 8,
thursday: 8,
friday: 8,
},
countryId: "country_de",
federalState: null,
metroCityId: null,
country: { code: "DE" },
metroCity: null,
},
]),
},
};
vi.mocked(listAssignmentBookings).mockResolvedValue([]);
const caller = createControllerCaller(db);
await caller.getChargeabilityStats({ resourceId: "resource_target" });
expect(db.resource.findMany).toHaveBeenCalledWith({
where: {
isActive: true,
id: "resource_target",
},
select: {
id: true,
eid: true,
displayName: true,
chapter: true,
chargeabilityTarget: true,
availability: true,
countryId: true,
federalState: true,
metroCityId: true,
country: { select: { code: true } },
metroCity: { select: { name: true } },
},
});
expect(listAssignmentBookings).toHaveBeenCalledWith(db, expect.objectContaining({
resourceIds: ["resource_target"],
}));
const [, bookingQuery] = vi.mocked(listAssignmentBookings).mock.calls.at(-1)!;
expect(bookingQuery.startDate).toEqual(new Date(2026, 2, 1));
expect(bookingQuery.endDate).toEqual(new Date(2026, 3, 0));
} finally {
vi.useRealTimers();
}
});
it("returns a holiday-aware chargeability summary readmodel", async () => {
const resourceRecord = {
id: "res_1",