147 lines
4.2 KiB
TypeScript
147 lines
4.2 KiB
TypeScript
import { TRPCError } from "@trpc/server";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
const {
|
|
findAllocationEntryMock,
|
|
updateAllocationEntryMock,
|
|
} = vi.hoisted(() => ({
|
|
findAllocationEntryMock: vi.fn(),
|
|
updateAllocationEntryMock: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@capakraken/application", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("@capakraken/application")>();
|
|
return {
|
|
...actual,
|
|
findAllocationEntry: findAllocationEntryMock,
|
|
updateAllocationEntry: updateAllocationEntryMock,
|
|
};
|
|
});
|
|
|
|
import { applyTimelineBatchAllocationShift } from "../router/timeline-allocation-shift-support.js";
|
|
|
|
describe("timeline allocation shift support", () => {
|
|
it("returns an empty result when the shift delta is zero", async () => {
|
|
const db = {
|
|
$transaction: vi.fn(),
|
|
};
|
|
|
|
await expect(applyTimelineBatchAllocationShift({
|
|
db: db as never,
|
|
allocationIds: ["allocation_1"],
|
|
daysDelta: 0,
|
|
mode: "move",
|
|
})).resolves.toEqual([]);
|
|
|
|
expect(findAllocationEntryMock).not.toHaveBeenCalled();
|
|
expect(db.$transaction).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("throws when no allocations can be resolved", async () => {
|
|
findAllocationEntryMock.mockResolvedValue(null);
|
|
|
|
await expect(applyTimelineBatchAllocationShift({
|
|
db: {
|
|
$transaction: vi.fn(),
|
|
} as never,
|
|
allocationIds: ["missing_1", "missing_2"],
|
|
daysDelta: 2,
|
|
mode: "move",
|
|
})).rejects.toThrowError(new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: "No allocations found",
|
|
}));
|
|
});
|
|
|
|
it("updates resolved allocations and writes a batch audit record", async () => {
|
|
findAllocationEntryMock
|
|
.mockResolvedValueOnce({
|
|
entry: {
|
|
id: "allocation_1",
|
|
startDate: new Date("2026-04-01T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-05T00:00:00.000Z"),
|
|
},
|
|
})
|
|
.mockResolvedValueOnce(null)
|
|
.mockResolvedValueOnce({
|
|
entry: {
|
|
id: "allocation_3",
|
|
startDate: new Date("2026-04-10T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-12T00:00:00.000Z"),
|
|
},
|
|
});
|
|
|
|
updateAllocationEntryMock
|
|
.mockResolvedValueOnce({
|
|
allocation: { id: "allocation_1", projectId: "project_1", resourceId: "resource_1" },
|
|
})
|
|
.mockResolvedValueOnce({
|
|
allocation: { id: "allocation_3", projectId: "project_2", resourceId: "resource_2" },
|
|
});
|
|
|
|
const tx = {
|
|
auditLog: {
|
|
create: vi.fn().mockResolvedValue({}),
|
|
},
|
|
};
|
|
const db = {
|
|
$transaction: vi.fn(async (callback: (client: typeof tx) => unknown) => callback(tx)),
|
|
};
|
|
|
|
const result = await applyTimelineBatchAllocationShift({
|
|
db: db as never,
|
|
allocationIds: ["allocation_1", "missing_2", "allocation_3"],
|
|
daysDelta: 2,
|
|
mode: "move",
|
|
});
|
|
|
|
expect(result).toEqual([
|
|
{ id: "allocation_1", projectId: "project_1", resourceId: "resource_1" },
|
|
{ id: "allocation_3", projectId: "project_2", resourceId: "resource_2" },
|
|
]);
|
|
expect(updateAllocationEntryMock).toHaveBeenNthCalledWith(
|
|
1,
|
|
tx,
|
|
{
|
|
id: "allocation_1",
|
|
demandRequirementUpdate: {
|
|
startDate: new Date("2026-04-03T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-07T00:00:00.000Z"),
|
|
},
|
|
assignmentUpdate: {
|
|
startDate: new Date("2026-04-03T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-07T00:00:00.000Z"),
|
|
},
|
|
},
|
|
);
|
|
expect(updateAllocationEntryMock).toHaveBeenNthCalledWith(
|
|
2,
|
|
tx,
|
|
{
|
|
id: "allocation_3",
|
|
demandRequirementUpdate: {
|
|
startDate: new Date("2026-04-12T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-14T00:00:00.000Z"),
|
|
},
|
|
assignmentUpdate: {
|
|
startDate: new Date("2026-04-12T00:00:00.000Z"),
|
|
endDate: new Date("2026-04-14T00:00:00.000Z"),
|
|
},
|
|
},
|
|
);
|
|
expect(tx.auditLog.create).toHaveBeenCalledWith({
|
|
data: {
|
|
entityType: "Allocation",
|
|
entityId: "allocation_1,missing_2,allocation_3",
|
|
action: "UPDATE",
|
|
changes: {
|
|
operation: "batchShift",
|
|
mode: "move",
|
|
daysDelta: 2,
|
|
count: 2,
|
|
},
|
|
},
|
|
});
|
|
});
|
|
});
|