46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parseRRule, nextOccurrence, validateMinInterval, MIN_INTERVAL_MS } from "./rrule.js";
|
|
|
|
describe("parseRRule", () => {
|
|
it("accepts a daily rule", () => {
|
|
expect(() => parseRRule("FREQ=DAILY;BYHOUR=9;BYMINUTE=0")).not.toThrow();
|
|
});
|
|
it("rejects invalid syntax", () => {
|
|
expect(() => parseRRule("not-a-rule")).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("nextOccurrence", () => {
|
|
it("returns the next firing time after `after`", () => {
|
|
const rule = "FREQ=DAILY;BYHOUR=9;BYMINUTE=0";
|
|
const after = new Date("2026-05-03T08:00:00Z");
|
|
const next = nextOccurrence(rule, "Asia/Kuala_Lumpur", after);
|
|
expect(next).toBeInstanceOf(Date);
|
|
expect(next!.getTime()).toBeGreaterThan(after.getTime());
|
|
});
|
|
it("returns null when the rule has no further occurrences", () => {
|
|
const past = "DTSTART:20200101T000000Z\nRRULE:FREQ=DAILY;COUNT=1";
|
|
expect(nextOccurrence(past, "Asia/Kuala_Lumpur", new Date())).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("validateMinInterval", () => {
|
|
it("accepts a daily rule (interval > 5 min)", () => {
|
|
expect(validateMinInterval("FREQ=DAILY;BYHOUR=9;BYMINUTE=0", "Asia/Kuala_Lumpur"))
|
|
.toEqual({ ok: true });
|
|
});
|
|
it("rejects a rule firing every minute", () => {
|
|
const result = validateMinInterval("FREQ=MINUTELY", "Asia/Kuala_Lumpur");
|
|
expect(result.ok).toBe(false);
|
|
if (!result.ok) {
|
|
expect(result.reason).toMatch(/minimum interval/i);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("MIN_INTERVAL_MS", () => {
|
|
it("equals 5 minutes", () => {
|
|
expect(MIN_INTERVAL_MS).toBe(5 * 60 * 1000);
|
|
});
|
|
});
|