"""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" )