"""CalDAV client pure helpers — XML multistatus / REPORT parsing + ICS round-trip."""
from __future__ import annotations
from datetime import UTC, datetime
from webmail_plugin_calendar.caldav import (
build_ics,
event_href,
parse_href,
parse_multistatus_calendars,
parse_report,
vevent_to_fields,
)
_PRINCIPAL_XML = """
/HTTP/1.1 200 OK
/123/principal/
"""
_CAL_LIST_XML = """
/123/calendars/home/HTTP/1.1 200 OK
/123/calendars/work/HTTP/1.1 200 OK
Work
#ff0000ff
ctag-42
/123/calendars/holidays/
HTTP/1.1 200 OK
Holidays
"""
_REPORT_XML = """
/123/calendars/work/ev1.ics
HTTP/1.1 200 OK
"etag-1"
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:ev1@example.com
SUMMARY:Standup
DTSTART:20260810T090000Z
DTEND:20260810T091500Z
END:VEVENT
END:VCALENDAR
"""
def test_parse_href_principal() -> None:
assert parse_href(_PRINCIPAL_XML, "{DAV:}current-user-principal") == "/123/principal/"
def test_parse_calendar_list_filters_and_reads_props() -> None:
cals = parse_multistatus_calendars(_CAL_LIST_XML, "https://dav.example.com/123/calendars/")
# The home collection (no resourcetype) is skipped; two calendars remain.
by_name = {c.name: c for c in cals}
assert set(by_name) == {"Work", "Holidays"}
work = by_name["Work"]
assert work.url == "https://dav.example.com/123/calendars/work/"
assert work.color == "#ff0000" # trimmed to #rrggbb
assert work.ctag == "ctag-42"
assert work.read_only is False # has
assert by_name["Holidays"].read_only is True # read privilege only
def test_parse_report_events() -> None:
events = parse_report(_REPORT_XML, "https://dav.example.com/123/calendars/work/")
assert len(events) == 1
ev = events[0]
assert ev.href == "https://dav.example.com/123/calendars/work/ev1.ics"
assert ev.etag == "etag-1" # quotes stripped
fields = vevent_to_fields(ev.ics)
assert fields is not None
assert fields["ical_uid"] == "ev1@example.com"
assert fields["summary"] == "Standup"
assert fields["dtstart"] == datetime(2026, 8, 10, 9, 0, tzinfo=UTC)
assert fields["all_day"] is False
def test_build_ics_roundtrips() -> None:
ics = build_ics(
{
"ical_uid": "made@ultimo",
"summary": "Lunch",
"location": "Cafe",
"dtstart": datetime(2026, 8, 11, 12, 0, tzinfo=UTC),
"dtend": datetime(2026, 8, 11, 13, 0, tzinfo=UTC),
"all_day": False,
"rrule": "FREQ=WEEKLY;BYDAY=MO",
}
)
fields = vevent_to_fields(ics)
assert fields is not None
assert fields["ical_uid"] == "made@ultimo"
assert fields["summary"] == "Lunch"
assert fields["location"] == "Cafe"
assert fields["rrule"] == "FREQ=WEEKLY;BYDAY=MO"
assert fields["dtstart"] == datetime(2026, 8, 11, 12, 0, tzinfo=UTC)
def test_event_href() -> None:
assert (
event_href("https://dav.example.com/cal/work", "abc@ex")
== "https://dav.example.com/cal/work/abc@ex.ics"
)