fix(caldav): expand RRULE for recurring events

This commit is contained in:
2026-09-06 15:49:09 +02:00
parent f35121b3dc
commit 8e946964ec
11 changed files with 1223 additions and 126 deletions
+22 -9
View File
@@ -49,6 +49,23 @@ func mustCalEvent(t *testing.T, raw string) ical.Event {
return evs[0]
}
// icssubSeriesID returns the stable ID the CalDAV backend advertises for the
// (single) series in raw. All tests here use single-series feeds, so this is
// just GroupSeries(raw)[0].ID().
func icssubSeriesID(t *testing.T, raw string) string {
t.Helper()
_ = t
cal, err := ical.NewDecoder(strings.NewReader(raw)).Decode()
if err != nil {
panic("icssubSeriesID: " + err.Error())
}
series := icssub.GroupSeries(cal)
if len(series) == 0 {
panic("icssubSeriesID: no series")
}
return series[0].ID()
}
// TestICSSubscriptionListAndGetObject verifies the full CalDAV read path
// for an ICS subscription: ListCalendarObjects returns one synthetic
// stand-alone object whose Path is derived from icssub.EventID (not from
@@ -92,16 +109,12 @@ func TestICSSubscriptionListAndGetObject(t *testing.T) {
t.Fatalf("expected 1 object, got %d", len(objs))
}
// The Path must be derived from the event's DTSTART/DTEND/SUMMARY
// i.e. icssub.EventID(ev), not from the event's position in the feed.
ev := mustCalEvent(t, icsSample)
wantID := icssub.EventID(ev)
if wantID == "" {
t.Fatal("EventID must be non-empty for a valid event")
}
// The Path must be derived from the event's stable identity (its UID)
// i.e. the series ID — not from the event's position in the feed.
wantID := icssubSeriesID(t, icsSample)
wantPath := calObjectPath("holidays", wantID)
if objs[0].Path != wantPath {
t.Fatalf("Path = %q, want %q (icssub.EventID-based, not position-based)", objs[0].Path, wantPath)
t.Fatalf("Path = %q, want %q (series-ID-based, not position-based)", objs[0].Path, wantPath)
}
// GetCalendarObject by the same Path should return an object that has
@@ -260,7 +273,7 @@ func TestICSSubscriptionEventIDMatchesEventInCalDav(t *testing.T) {
t.Fatalf("list: objs=%d err=%v", len(objs), err)
}
gotPath := objs[0].Path
wantID := icssub.EventID(mustCalEvent(t, icsSample))
wantID := icssubSeriesID(t, icsSample)
wantPath := calObjectPath("holidays", wantID)
if gotPath != wantPath {
t.Fatalf("CalDAV object path %q does not match web-side EventID-derived %q", gotPath, wantPath)