import { describe, expect, it } from "vitest"; import { isRecurringDay, getRecurringHoursForDay } from "../allocation/recurrence.js"; import { RecurrenceFrequency } from "@capakraken/shared"; import type { RecurrencePattern } from "@capakraken/shared"; const monday = new Date("2026-03-09"); // Monday const tuesday = new Date("2026-03-10"); // Tuesday const wednesday = new Date("2026-03-11"); // Wednesday const friday = new Date("2026-03-13"); // Friday const nextMonday = new Date("2026-03-16"); // Monday (next week) const twoWeeksMonday = new Date("2026-03-23"); // Monday (two weeks after) const allocationStart = new Date("2026-03-09"); // Monday describe("isRecurringDay", () => { describe("WEEKLY", () => { const pattern: RecurrencePattern = { frequency: RecurrenceFrequency.WEEKLY, weekdays: [1, 3, 5], // Mon, Wed, Fri }; it("returns true for days matching weekday list", () => { expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true); expect(isRecurringDay(wednesday, pattern, allocationStart)).toBe(true); expect(isRecurringDay(friday, pattern, allocationStart)).toBe(true); }); it("returns false for days not in weekday list", () => { expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(false); }); }); describe("BIWEEKLY", () => { const pattern: RecurrencePattern = { frequency: RecurrenceFrequency.BIWEEKLY, weekdays: [1], // Monday only interval: 2, }; it("returns true on the allocation start week (week 0)", () => { expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true); }); it("returns false on the next week (week 1, odd)", () => { expect(isRecurringDay(nextMonday, pattern, allocationStart)).toBe(false); }); it("returns true two weeks after start (week 2, even)", () => { expect(isRecurringDay(twoWeeksMonday, pattern, allocationStart)).toBe(true); }); it("returns false for non-matching weekdays even in active weeks", () => { expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(false); }); }); describe("MONTHLY", () => { const pattern: RecurrencePattern = { frequency: RecurrenceFrequency.MONTHLY, monthDay: 15, }; it("returns true on the specified day of month", () => { expect(isRecurringDay(new Date("2026-03-15"), pattern, allocationStart)).toBe(true); }); it("returns false on other days", () => { expect(isRecurringDay(new Date("2026-03-14"), pattern, allocationStart)).toBe(false); }); it("returns false when monthDay is undefined", () => { const noDay: RecurrencePattern = { frequency: RecurrenceFrequency.MONTHLY, }; expect(isRecurringDay(new Date("2026-03-15"), noDay, allocationStart)).toBe(false); }); }); describe("CUSTOM", () => { const pattern: RecurrencePattern = { frequency: RecurrenceFrequency.CUSTOM, }; it("always returns true", () => { expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true); expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(true); }); }); }); describe("getRecurringHoursForDay", () => { const weeklyPattern: RecurrencePattern = { frequency: RecurrenceFrequency.WEEKLY, weekdays: [1, 3, 5], // Mon, Wed, Fri }; it("returns default hours on recurring days", () => { expect(getRecurringHoursForDay(monday, weeklyPattern, 8, allocationStart)).toBe(8); }); it("returns 0 on non-recurring days", () => { expect(getRecurringHoursForDay(tuesday, weeklyPattern, 8, allocationStart)).toBe(0); }); it("uses pattern.hoursPerDay when set", () => { const patternWithHours: RecurrencePattern = { ...weeklyPattern, hoursPerDay: 4, }; expect(getRecurringHoursForDay(monday, patternWithHours, 8, allocationStart)).toBe(4); }); it("returns 0 before pattern startDate", () => { const patternWithStart: RecurrencePattern = { ...weeklyPattern, startDate: "2026-03-16", }; expect(getRecurringHoursForDay(monday, patternWithStart, 8, allocationStart)).toBe(0); }); it("returns 0 after pattern endDate", () => { const patternWithEnd: RecurrencePattern = { ...weeklyPattern, endDate: "2026-03-08", }; expect(getRecurringHoursForDay(monday, patternWithEnd, 8, allocationStart)).toBe(0); }); it("returns hours within pattern date bounds", () => { const bounded: RecurrencePattern = { ...weeklyPattern, startDate: "2026-03-01", endDate: "2026-03-31", }; expect(getRecurringHoursForDay(monday, bounded, 8, allocationStart)).toBe(8); }); });