feat: add shared recurrence helpers
This commit is contained in:
83
tests/recurrence.test.ts
Normal file
83
tests/recurrence.test.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
formatRecurrenceText,
|
||||
getRecurrencePreview,
|
||||
parseRecurrenceRule,
|
||||
serializeRecurrenceRule,
|
||||
validateRecurrence,
|
||||
} from "@/lib/recurrence";
|
||||
|
||||
describe("recurrence helpers", () => {
|
||||
test("serializes a weekly weekday recurrence into an RFC5545 RRULE string", () => {
|
||||
const rule = serializeRecurrenceRule({
|
||||
freq: "WEEKLY",
|
||||
interval: 2,
|
||||
byDay: ["TU", "TH"],
|
||||
until: "2026-06-30",
|
||||
});
|
||||
|
||||
expect(rule).toBe("FREQ=WEEKLY;INTERVAL=2;UNTIL=20260630T235959Z;BYDAY=TU,TH");
|
||||
});
|
||||
|
||||
test("rehydrates an existing RRULE string into picker-friendly values", () => {
|
||||
const parsed = parseRecurrenceRule(
|
||||
"FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR;COUNT=6",
|
||||
);
|
||||
|
||||
expect(parsed).toEqual({
|
||||
freq: "WEEKLY",
|
||||
interval: 1,
|
||||
byDay: ["MO", "WE", "FR"],
|
||||
count: 6,
|
||||
until: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test("returns a preview of upcoming recurrence instances from the public helper", () => {
|
||||
const preview = getRecurrencePreview(
|
||||
{
|
||||
freq: "MONTHLY",
|
||||
interval: 1,
|
||||
byDay: [],
|
||||
count: 3,
|
||||
},
|
||||
"2026-04-09T10:00:00.000Z",
|
||||
);
|
||||
|
||||
expect(preview).toHaveLength(3);
|
||||
expect(preview[0]).toContain("2026-04-09T10:00:00.000Z");
|
||||
expect(preview[1]).toContain("2026-05-09T10:00:00.000Z");
|
||||
expect(preview[2]).toContain("2026-06-09T10:00:00.000Z");
|
||||
});
|
||||
|
||||
test("rejects invalid recurrence endings that mix count and until", () => {
|
||||
const result = validateRecurrence({
|
||||
freq: "DAILY",
|
||||
interval: 1,
|
||||
byDay: [],
|
||||
count: 5,
|
||||
until: "2026-05-01",
|
||||
});
|
||||
|
||||
expect(result.isValid).toBe(false);
|
||||
expect(result.errors.rule).toContain("either count or until");
|
||||
});
|
||||
|
||||
test("rejects malformed count inputs", () => {
|
||||
const result = validateRecurrence({
|
||||
freq: "MONTHLY",
|
||||
interval: 1,
|
||||
byDay: [],
|
||||
count: 0,
|
||||
});
|
||||
|
||||
expect(result.isValid).toBe(false);
|
||||
expect(result.errors.count).toContain("greater than 0");
|
||||
});
|
||||
|
||||
test("formats supported recurrence strings into human text", () => {
|
||||
expect(formatRecurrenceText("FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE")).toContain(
|
||||
"every week",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user