114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from datetime import datetime, timezone
|
|
|
|
from govoplan_calendar.backend.ews import (
|
|
EwsAdapterError,
|
|
ews_find_item_body,
|
|
parse_ews_calendar_items,
|
|
)
|
|
from govoplan_calendar.backend.graph import graph_event_payload
|
|
|
|
|
|
class ProviderAdapterTests(unittest.TestCase):
|
|
def test_graph_event_fixture_maps_provider_fields(self) -> None:
|
|
payload = graph_event_payload(
|
|
{
|
|
"id": "graph-event-1",
|
|
"iCalUId": "uid-1@example.test",
|
|
"@odata.etag": 'W/"etag-1"',
|
|
"type": "occurrence",
|
|
"subject": "Planning",
|
|
"body": {"content": "Agenda"},
|
|
"start": {
|
|
"dateTime": "2026-07-08T09:00:00",
|
|
"timeZone": "Europe/Berlin",
|
|
},
|
|
"end": {
|
|
"dateTime": "2026-07-08T10:30:00",
|
|
"timeZone": "Europe/Berlin",
|
|
},
|
|
"organizer": {
|
|
"emailAddress": {
|
|
"name": "Ada",
|
|
"address": "ada@example.test",
|
|
}
|
|
},
|
|
"attendees": [
|
|
{
|
|
"type": "required",
|
|
"emailAddress": {
|
|
"name": "Lin",
|
|
"address": "lin@example.test",
|
|
},
|
|
}
|
|
],
|
|
"isReminderOn": True,
|
|
"reminderMinutesBeforeStart": 15,
|
|
}
|
|
)
|
|
|
|
self.assertEqual(payload["uid"], "uid-1@example.test")
|
|
self.assertEqual(payload["recurrence_id"], "graph-event-1")
|
|
self.assertEqual(
|
|
payload["start_at"],
|
|
datetime(2026, 7, 8, 7, 0, tzinfo=timezone.utc),
|
|
)
|
|
self.assertEqual(payload["duration_seconds"], 5_400)
|
|
self.assertEqual(
|
|
payload["attendees"][0]["email"],
|
|
"lin@example.test",
|
|
)
|
|
self.assertEqual(
|
|
payload["reminders"][0]["trigger_minutes_before"],
|
|
15,
|
|
)
|
|
|
|
def test_ews_calendar_fixture_maps_item_and_escapes_mailbox(self) -> None:
|
|
response_xml = """<?xml version="1.0" encoding="utf-8"?>
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
|
|
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
|
|
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
|
|
<s:Body><m:FindItemResponse><m:ResponseMessages>
|
|
<m:FindItemResponseMessage ResponseClass="Success"><m:RootFolder>
|
|
<t:Items><t:CalendarItem>
|
|
<t:ItemId Id="ews-event-1" ChangeKey="ews-etag-1" />
|
|
<t:Subject>EWS item</t:Subject>
|
|
<t:Start>2026-07-08T09:00:00Z</t:Start>
|
|
<t:End>2026-07-08T10:00:00Z</t:End>
|
|
<t:IsAllDayEvent>false</t:IsAllDayEvent>
|
|
<t:UID>ews-uid-1</t:UID>
|
|
<t:RequiredAttendees><t:Attendee><t:Mailbox>
|
|
<t:Name>Ada</t:Name>
|
|
<t:EmailAddress>ada@example.test</t:EmailAddress>
|
|
</t:Mailbox></t:Attendee></t:RequiredAttendees>
|
|
</t:CalendarItem></t:Items>
|
|
</m:RootFolder></m:FindItemResponseMessage>
|
|
</m:ResponseMessages></m:FindItemResponse></s:Body>
|
|
</s:Envelope>"""
|
|
|
|
items = parse_ews_calendar_items(response_xml)
|
|
|
|
self.assertEqual(len(items), 1)
|
|
self.assertEqual(items[0]["href"], "ews-event-1")
|
|
self.assertEqual(items[0]["etag"], "ews-etag-1")
|
|
self.assertEqual(
|
|
items[0]["attendees"][0]["email"],
|
|
"ada@example.test",
|
|
)
|
|
request_body = ews_find_item_body(
|
|
start=datetime(2026, 7, 1, tzinfo=timezone.utc),
|
|
end=datetime(2026, 8, 1, tzinfo=timezone.utc),
|
|
mailbox='ops&"<@example.test',
|
|
)
|
|
self.assertIn("ops&"<@example.test", request_body)
|
|
|
|
def test_ews_parser_rejects_invalid_xml(self) -> None:
|
|
with self.assertRaisesRegex(EwsAdapterError, "Invalid EWS"):
|
|
parse_ews_calendar_items("<not-closed>")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|