Rules alone were still wrong, in the other direction. A live 0.16.19 was asked to expand a real weekly series: the occurrences come back carrying no rule at all — only the master has one — and Stalwart spells that master's rule "recurrenceRule", singular, not the RFC 8984 array ihasmail looks for. So a genuine occurrence would have read as a one-off, and the delete dialog would have offered to delete "this event" while deleting the series. What an occurrence does carry is a recurrenceId, which a one-off never has. Master by its rule under either name, occurrence by its recurrenceId. The tests carry the shapes the live server returned.
34 lines
2.0 KiB
TypeScript
34 lines
2.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { isRecurring } from "@/store/calendar";
|
|
import type { CalendarEvent } from "@/jmap/types";
|
|
|
|
/**
|
|
* `CalendarEvent/query` runs with `expandRecurrences`, and Stalwart puts a
|
|
* `baseEventId` on everything it returns that way — one-off events included.
|
|
* Treating that as proof of a series told people editing a plain event that
|
|
* their changes applied to the whole series, and offered to delete "all
|
|
* occurrences" of an event that has exactly one.
|
|
*/
|
|
const ev = (p: Partial<CalendarEvent>): CalendarEvent => ({ id: "ev1", "@type": "Event", uid: "u1", calendarIds: { c1: true }, start: "2026-08-25T09:00:00", duration: "PT30M", ...p } as CalendarEvent);
|
|
|
|
describe("isRecurring", () => {
|
|
it("does not call a one-off event a series just because it has a baseEventId", () => {
|
|
expect(isRecurring(ev({ baseEventId: "ev1" }))).toBe(false);
|
|
expect(isRecurring(ev({}))).toBe(false);
|
|
// The shape a live 0.16.19 returns for a one-off: an instance id of its own,
|
|
// and a base that is a different id. Neither makes it a series.
|
|
expect(isRecurring(ev({ id: "eaaaaai", baseEventId: "i" }))).toBe(false);
|
|
});
|
|
it("recognises a series by its rule, under either name", () => {
|
|
expect(isRecurring(ev({ recurrenceRules: [{ "@type": "RecurrenceRule", frequency: "weekly" }] }))).toBe(true);
|
|
expect(isRecurring(ev({ excludedRecurrenceRules: [{ "@type": "RecurrenceRule", frequency: "monthly" }] }))).toBe(true);
|
|
// Stalwart 0.16 keeps a single rule under the singular name.
|
|
expect(isRecurring(ev({ recurrenceRule: { "@type": "RecurrenceRule", frequency: "weekly", count: 3 } }))).toBe(true);
|
|
});
|
|
it("recognises an occurrence, which arrives with no rule of its own", () => {
|
|
// A live 0.16.19 expands a weekly series into instances like this: an id
|
|
// per occurrence, a recurrenceId, and no rule attached.
|
|
expect(isRecurring(ev({ id: "iaaaaas", recurrenceId: "2030-03-11T10:00:00" }))).toBe(true);
|
|
});
|
|
});
|