Files
local-cal/tests/recurrence.test.ts

84 lines
2.0 KiB
TypeScript

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",
);
});
});