import { describe, expect, it } from "vitest"; import { addDays, addMonths, describeRecurrence, isFinished, listOccurrences, occurrenceDate, type Recurrence, } from "./recurrence"; const rule = (over: Partial): Recurrence => ({ frequency: "monthly", interval: 1, monthlyMode: "day", startDate: "2026-01-31", endDate: null, count: null, ...over, }); describe("tarih aritmetiği", () => { it("gün ve ay ekleme, ay sonu taşması", () => { expect(addDays("2026-12-30", 3)).toBe("2027-01-02"); expect(addDays("2028-03-01", -1)).toBe("2028-02-29"); expect(addMonths("2026-01-31", 1)).toBe("2026-02-28"); expect(addMonths("2026-01-31", 1, 31)).toBe("2026-02-28"); expect(addMonths("2026-11-15", 3)).toBe("2027-02-15"); expect(addMonths("2026-04-10", 0, "last")).toBe("2026-04-30"); }); }); describe("occurrenceDate", () => { it("aylık: başlangıç günü korunur, ayda yoksa son gün", () => { const r = rule({}); expect([0, 1, 2, 3].map((i) => occurrenceDate(r, i))).toEqual([ "2026-01-31", "2026-02-28", "2026-03-31", "2026-04-30", ]); }); it("aylık son gün modu (artık yıl dahil)", () => { const r = rule({ monthlyMode: "last", startDate: "2028-01-10" }); expect([0, 1, 2].map((i) => occurrenceDate(r, i))).toEqual([ "2028-01-31", "2028-02-29", "2028-03-31", ]); }); it("günlük, haftalık (aralıkla), yıllık (29 Şubat)", () => { expect( occurrenceDate(rule({ frequency: "daily", interval: 3, startDate: "2026-11-30" }), 1), ).toBe("2026-12-03"); expect( occurrenceDate(rule({ frequency: "weekly", interval: 2, startDate: "2026-11-02" }), 2), ).toBe("2026-11-30"); const y = rule({ frequency: "yearly", startDate: "2028-02-29" }); expect([1, 4].map((i) => occurrenceDate(y, i))).toEqual(["2029-02-28", "2032-02-29"]); }); }); describe("listOccurrences", () => { it("tekrar sayısı, bitiş tarihi ve ufuk sınırları", () => { const r = rule({ startDate: "2026-01-05", count: 3 }); expect(listOccurrences(r, "2030-01-01").map((o) => o.date)).toEqual([ "2026-01-05", "2026-02-05", "2026-03-05", ]); expect(isFinished(r, 3)).toBe(true); const e = rule({ startDate: "2026-01-05", endDate: "2026-02-10" }); expect(listOccurrences(e, "2030-01-01")).toHaveLength(2); const h = rule({ startDate: "2026-01-05" }); expect(listOccurrences(h, "2026-04-05").map((o) => o.index)).toEqual([0, 1, 2, 3]); expect(listOccurrences(h, "2026-04-05", 2).map((o) => o.index)).toEqual([2, 3]); expect(isFinished(h, 100)).toBe(false); }); }); describe("describeRecurrence", () => { it("Türkçe açıklama", () => { expect(describeRecurrence(rule({ startDate: "2026-11-03" }))).toBe("Her ay 3. gün"); expect(describeRecurrence(rule({ monthlyMode: "last" }))).toBe("Her ayın son günü"); expect( describeRecurrence(rule({ frequency: "weekly", interval: 2, startDate: "2026-11-02" })), ).toBe("2 haftada bir Pazartesi"); expect(describeRecurrence(rule({ frequency: "yearly", startDate: "2026-03-15" }))).toBe( "Her yıl 15 Mart", ); expect(describeRecurrence(rule({ frequency: "daily" }))).toBe("Her gün"); }); });