const { calculateRequestedDays, leaveRangesOverlap, summarizeLeaveLedgerEntries, } = require("../../../src/services/leave"); describe("Leave Service", () => { describe("calculateRequestedDays", () => { it("supports same-day half-day requests", () => { expect( calculateRequestedDays({ startDate: "2026-03-10", endDate: "2026-03-10", startSession: "am", endSession: "am", }), ).toBe(0.5); expect( calculateRequestedDays({ startDate: "2026-03-10", endDate: "2026-03-10", startSession: "pm", endSession: "pm", }), ).toBe(0.5); }); it("supports cross-day half-day boundaries", () => { expect( calculateRequestedDays({ startDate: "2026-03-10", endDate: "2026-03-12", startSession: "pm", endSession: "am", }), ).toBe(2); }); it("rejects invalid session ranges", () => { expect(() => calculateRequestedDays({ startDate: "2026-03-10", endDate: "2026-03-10", startSession: "pm", endSession: "am", }), ).toThrow(/参数校验失败/); }); }); describe("leaveRangesOverlap", () => { it("detects overlapping half-day ranges", () => { expect( leaveRangesOverlap( { startDate: "2026-03-10", endDate: "2026-03-11", startSession: "pm", endSession: "pm", }, { startDate: "2026-03-11", endDate: "2026-03-12", startSession: "am", endSession: "am", }, ), ).toBe(true); }); it("does not flag non-overlapping adjacent ranges", () => { expect( leaveRangesOverlap( { startDate: "2026-03-10", endDate: "2026-03-10", startSession: "am", endSession: "am", }, { startDate: "2026-03-10", endDate: "2026-03-10", startSession: "pm", endSession: "pm", }, ), ).toBe(false); }); }); describe("summarizeLeaveLedgerEntries", () => { it("calculates reserve / consume / release balances correctly", () => { const summary = summarizeLeaveLedgerEntries([ { entry_type: "grant", days: 10 }, { entry_type: "reserve", days: 2.5 }, { entry_type: "release", days: 1 }, { entry_type: "consume", days: 1.5 }, ]); expect(summary.granted).toBe(10); expect(summary.reserved).toBe(1.5); expect(summary.used).toBe(1.5); expect(summary.available).toBe(7); }); }); });