refactor(api): extract timeline allocation mutation support

This commit is contained in:
2026-03-31 15:06:38 +02:00
parent b05758db69
commit b1ada431e1
3 changed files with 265 additions and 77 deletions
@@ -0,0 +1,101 @@
import { TRPCError } from "@trpc/server";
import { describe, expect, it } from "vitest";
import {
assertTimelineDateRangeValid,
buildTimelineAllocationMetadata,
buildTimelineBatchShiftAuditChanges,
buildTimelineQuickAssignMetadata,
calculateTimelineAllocationPercentage,
shiftTimelineAllocationWindow,
} from "../router/timeline-allocation-mutation-support.js";
describe("timeline allocation mutation support", () => {
it("preserves existing metadata while updating includeSaturday", () => {
const result = buildTimelineAllocationMetadata({
existingMetadata: {
recurrence: { frequency: "weekly", interval: 2 },
includeSaturday: false,
},
includeSaturday: true,
});
expect(result).toEqual({
metadata: {
recurrence: { frequency: "weekly", interval: 2 },
includeSaturday: true,
},
includeSaturday: true,
});
});
it("rejects inverted date ranges", () => {
expect(() =>
assertTimelineDateRangeValid(
new Date("2026-04-10T00:00:00.000Z"),
new Date("2026-04-09T00:00:00.000Z"),
)).toThrowError(TRPCError);
});
it("rounds allocation percentages and clamps them to 100", () => {
expect(calculateTimelineAllocationPercentage(3.9)).toBe(49);
expect(calculateTimelineAllocationPercentage(9)).toBe(100);
});
it("builds source metadata for quick assign operations", () => {
expect(buildTimelineQuickAssignMetadata("quickAssign")).toEqual({ source: "quickAssign" });
expect(buildTimelineQuickAssignMetadata("batchQuickAssign")).toEqual({ source: "batchQuickAssign" });
});
it("shifts and clamps allocation windows for each batch-shift mode", () => {
expect(
shiftTimelineAllocationWindow({
startDate: new Date("2026-04-10T00:00:00.000Z"),
endDate: new Date("2026-04-12T00:00:00.000Z"),
daysDelta: 2,
mode: "move",
}),
).toEqual({
startDate: new Date("2026-04-12T00:00:00.000Z"),
endDate: new Date("2026-04-14T00:00:00.000Z"),
});
expect(
shiftTimelineAllocationWindow({
startDate: new Date("2026-04-10T00:00:00.000Z"),
endDate: new Date("2026-04-12T00:00:00.000Z"),
daysDelta: 5,
mode: "resize-start",
}),
).toEqual({
startDate: new Date("2026-04-12T00:00:00.000Z"),
endDate: new Date("2026-04-12T00:00:00.000Z"),
});
expect(
shiftTimelineAllocationWindow({
startDate: new Date("2026-04-10T00:00:00.000Z"),
endDate: new Date("2026-04-12T00:00:00.000Z"),
daysDelta: -5,
mode: "resize-end",
}),
).toEqual({
startDate: new Date("2026-04-10T00:00:00.000Z"),
endDate: new Date("2026-04-10T00:00:00.000Z"),
});
});
it("builds batch-shift audit payloads", () => {
expect(
buildTimelineBatchShiftAuditChanges({
mode: "move",
daysDelta: 3,
count: 2,
}),
).toEqual({
operation: "batchShift",
mode: "move",
daysDelta: 3,
count: 2,
});
});
});