116 lines
4.3 KiB
Python
116 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from datetime import datetime, timedelta, timezone
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
from govoplan_calendar.backend.schemas import CalendarCollectionDeleteRequest, CalendarEventResponse
|
|
from govoplan_calendar.backend.service import delete_calendar, event_response
|
|
|
|
|
|
class FakeSession:
|
|
def __init__(self) -> None:
|
|
self.flushed = False
|
|
|
|
def flush(self) -> None:
|
|
self.flushed = True
|
|
|
|
|
|
class CalendarServiceResponseTests(unittest.TestCase):
|
|
def test_event_response_marks_naive_database_datetimes_as_utc(self) -> None:
|
|
event = SimpleNamespace(
|
|
id="event-1",
|
|
tenant_id="tenant-1",
|
|
calendar_id="calendar-1",
|
|
uid="event-1@example.test",
|
|
recurrence_id=None,
|
|
sequence=0,
|
|
summary="Planning",
|
|
description=None,
|
|
location=None,
|
|
status="CONFIRMED",
|
|
transparency="OPAQUE",
|
|
classification="PUBLIC",
|
|
start_at=datetime(2026, 7, 7, 18, 0),
|
|
end_at=datetime(2026, 7, 7, 19, 0),
|
|
duration_seconds=None,
|
|
all_day=False,
|
|
timezone=None,
|
|
organizer=None,
|
|
attendees=[],
|
|
categories=[],
|
|
rrule=None,
|
|
rdate=[],
|
|
exdate=[],
|
|
reminders=[],
|
|
attachments=[],
|
|
related_to=[],
|
|
source_kind="local",
|
|
source_href=None,
|
|
etag=None,
|
|
icalendar={},
|
|
created_at=datetime(2026, 7, 7, 17, 55),
|
|
updated_at=datetime(2026, 7, 7, 17, 55),
|
|
metadata_={},
|
|
)
|
|
|
|
payload = event_response(event)
|
|
response = CalendarEventResponse.model_validate(payload)
|
|
|
|
self.assertEqual(response.start_at.utcoffset(), timedelta(0))
|
|
self.assertEqual(response.end_at.utcoffset(), timedelta(0))
|
|
self.assertEqual(response.created_at.utcoffset(), timedelta(0))
|
|
self.assertEqual(response.updated_at.utcoffset(), timedelta(0))
|
|
self.assertEqual(response.start_at.tzinfo, timezone.utc)
|
|
|
|
|
|
class CalendarServiceDeleteTests(unittest.TestCase):
|
|
def test_delete_default_calendar_soft_deletes_calendar_and_events(self) -> None:
|
|
session = FakeSession()
|
|
event = SimpleNamespace(calendar_id="calendar-1", deleted_at=None)
|
|
calendar = SimpleNamespace(id="calendar-1", is_default=True, deleted_at=None, events=[event])
|
|
|
|
with patch("govoplan_calendar.backend.service.get_calendar", return_value=calendar):
|
|
delete_calendar(
|
|
session,
|
|
tenant_id="tenant-1",
|
|
calendar_id="calendar-1",
|
|
payload=CalendarCollectionDeleteRequest(event_action="delete"),
|
|
)
|
|
|
|
self.assertTrue(session.flushed)
|
|
self.assertFalse(calendar.is_default)
|
|
self.assertIsNotNone(calendar.deleted_at)
|
|
self.assertEqual(event.deleted_at, calendar.deleted_at)
|
|
self.assertEqual(event.calendar_id, "calendar-1")
|
|
|
|
def test_delete_calendar_can_move_events_to_another_calendar_and_make_it_default(self) -> None:
|
|
session = FakeSession()
|
|
event = SimpleNamespace(calendar_id="calendar-1", deleted_at=None)
|
|
calendar = SimpleNamespace(id="calendar-1", is_default=True, deleted_at=None, events=[event])
|
|
target = SimpleNamespace(id="calendar-2", is_default=False, deleted_at=None, events=[])
|
|
|
|
with (
|
|
patch("govoplan_calendar.backend.service.get_calendar", side_effect=[calendar, target]),
|
|
patch("govoplan_calendar.backend.service.clear_default_calendar") as clear_default_calendar,
|
|
):
|
|
delete_calendar(
|
|
session,
|
|
tenant_id="tenant-1",
|
|
calendar_id="calendar-1",
|
|
payload=CalendarCollectionDeleteRequest(event_action="move", target_calendar_id="calendar-2", make_target_default=True),
|
|
)
|
|
|
|
self.assertTrue(session.flushed)
|
|
clear_default_calendar.assert_called_once_with(session, tenant_id="tenant-1")
|
|
self.assertFalse(calendar.is_default)
|
|
self.assertTrue(target.is_default)
|
|
self.assertIsNotNone(calendar.deleted_at)
|
|
self.assertIsNone(event.deleted_at)
|
|
self.assertEqual(event.calendar_id, "calendar-2")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|