From ac44076bd889e7c193325b3ecb67f04ff1a337b6 Mon Sep 17 00:00:00 2001
From: Roger Gonzalez <roger@rogs.me>
Date: Fri, 6 Dec 2024 18:08:44 -0300
Subject: [PATCH] Added tests for fetch_events

---
 tests/test_caldav_client.py | 242 +++++++++++++++++++++++++++++++++++-
 1 file changed, 241 insertions(+), 1 deletion(-)

diff --git a/tests/test_caldav_client.py b/tests/test_caldav_client.py
index 3b952cb..426419d 100644
--- a/tests/test_caldav_client.py
+++ b/tests/test_caldav_client.py
@@ -5,8 +5,9 @@ from unittest.mock import MagicMock
 
 import pytest
 from caldav import DAVClient, Principal
+from icalendar import Calendar, Event
 
-from src.caldav_client import _process_exdate, connect_to_caldav, get_calendar
+from src.caldav_client import _process_exdate, connect_to_caldav, fetch_events, get_calendar
 
 
 class MockDatetime:
@@ -266,3 +267,242 @@ def test_process_exdate_empty_dates_list():
     result = _process_exdate(mock_dt)
 
     assert result == []
+
+
+def create_mock_event(  # noqa PLR0913
+    uid,
+    summary,
+    start_time,
+    end_time,
+    last_modified=None,
+    description=None,
+    location=None,
+    rrule=None,
+    exdate=None,
+    recurrence_id=None,
+):
+    """Create a mock CalDAV event."""
+    event = Event()
+    event.add("uid", uid)
+    event.add("summary", summary)
+    event.add("dtstart", start_time)
+    event.add("dtend", end_time)
+
+    if last_modified:
+        event.add("last-modified", last_modified)
+    if description:
+        event.add("description", description)
+    if location:
+        event.add("location", location)
+    if rrule:
+        event.add("rrule", rrule)
+    if exdate:
+        event.add("exdate", exdate)
+    if recurrence_id:
+        event.add("recurrence-id", recurrence_id)
+
+    cal = Calendar()
+    cal.add_component(event)
+
+    mock_event = MagicMock()
+    mock_event.data = cal.to_ical()
+    return mock_event
+
+
+def test_fetch_events_single_event():
+    """Test fetching a single simple event."""
+    start_time = datetime(2024, 1, 1, 10, 0, tzinfo=timezone.utc)
+    end_time = datetime(2024, 1, 1, 11, 0, tzinfo=timezone.utc)
+    last_modified = datetime(2024, 1, 1, 9, 0, tzinfo=timezone.utc)
+
+    mock_event = create_mock_event(
+        uid="test-event-1",
+        summary="Test Event",
+        start_time=start_time,
+        end_time=end_time,
+        last_modified=last_modified,
+        description="Test Description",
+        location="Test Location",
+    )
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = [mock_event]
+
+    result = fetch_events(mock_calendar)
+
+    assert len(result) == 1
+    event = result["test-event-1"]
+    assert event["uid"] == "test-event-1"
+    assert event["summary"] == "Test Event"
+    assert event["description"] == "Test Description"
+    assert event["location"] == "Test Location"
+    assert event["start"] == start_time.isoformat()
+    assert event["end"] == end_time.isoformat()
+    assert event["last_modified"] == last_modified.isoformat()
+    assert event["rrule"] is None
+    assert event["exdate"] is None
+    assert event["recurrence_id"] is None
+
+
+def test_fetch_events_recurring_event():
+    """Test fetching a recurring event with exceptions."""
+    start_time = datetime(2024, 1, 1, 10, 0, tzinfo=timezone.utc)
+    end_time = datetime(2024, 1, 1, 11, 0, tzinfo=timezone.utc)
+
+    rrule = {
+        "FREQ": ["WEEKLY"],
+        "COUNT": [4],
+        "BYDAY": ["MO", "WE", "FR"],
+    }
+
+    exdate = datetime(2024, 1, 8, 10, 0, tzinfo=timezone.utc)
+
+    mock_event = create_mock_event(
+        uid="recurring-event-1",
+        summary="Recurring Meeting",
+        start_time=start_time,
+        end_time=end_time,
+        rrule=rrule,
+        exdate=exdate,
+    )
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = [mock_event]
+
+    result = fetch_events(mock_calendar)
+
+    assert len(result) == 1
+    event = result["recurring-event-1"]
+    assert event["uid"] == "recurring-event-1"
+    assert event["rrule"] == rrule
+    assert event["exdate"] == [exdate.isoformat()]
+
+
+def test_fetch_events_recurring_instance():
+    """Test fetching a specific instance of a recurring event."""
+    start_time = datetime(2024, 1, 1, 10, 0, tzinfo=timezone.utc)
+    end_time = datetime(2024, 1, 1, 11, 0, tzinfo=timezone.utc)
+    recurrence_id = datetime(2024, 1, 8, 10, 0, tzinfo=timezone.utc)
+
+    mock_event = create_mock_event(
+        uid="recurring-event-1",
+        summary="Modified Instance",
+        start_time=start_time,
+        end_time=end_time,
+        recurrence_id=recurrence_id,
+    )
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = [mock_event]
+
+    result = fetch_events(mock_calendar)
+
+    assert len(result) == 1
+    event_key = "recurring-event-1-2024-01-08T10:00:00+00:00"
+    assert event_key in result
+    assert result[event_key]["recurrence_id"] == recurrence_id.isoformat()
+
+
+def test_fetch_events_multiple_events():
+    """Test fetching multiple events with different properties."""
+    events = [
+        create_mock_event(
+            uid="event-1",
+            summary="Regular Event",
+            start_time=datetime(2024, 1, 1, 10, 0, tzinfo=timezone.utc),
+            end_time=datetime(2024, 1, 1, 11, 0, tzinfo=timezone.utc),
+        ),
+        create_mock_event(
+            uid="event-2",
+            summary="Recurring Event",
+            start_time=datetime(2024, 1, 2, 14, 0, tzinfo=timezone.utc),
+            end_time=datetime(2024, 1, 2, 15, 0, tzinfo=timezone.utc),
+            rrule={"FREQ": ["DAILY"], "COUNT": [3]},
+        ),
+    ]
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = events
+
+    result = fetch_events(mock_calendar)
+
+    assert len(result) == 2  # noqa PLR2004
+    assert "event-1" in result
+    assert "event-2" in result
+    assert result["event-2"]["rrule"] == {"FREQ": ["DAILY"], "COUNT": [3]}
+
+
+def test_fetch_events_empty_calendar():
+    """Test fetching events from an empty calendar."""
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Empty Calendar"
+    mock_calendar.events.return_value = []
+
+    result = fetch_events(mock_calendar)
+
+    assert isinstance(result, dict)
+    assert len(result) == 0
+
+
+def test_fetch_events_error_handling():
+    """Test handling of errors when fetching events."""
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.side_effect = Exception("Failed to fetch events")
+
+    with pytest.raises(Exception, match="Failed to fetch events"):
+        fetch_events(mock_calendar)
+
+
+def test_fetch_events_malformed_event():
+    """Test handling of malformed event data."""
+    event1 = Event()
+    event2 = Event()
+    event2.add("uid", "good-event")
+
+    cal1 = Calendar()
+    cal1.add_component(event1)
+    mock_event1 = MagicMock()
+    mock_event1.data = cal1.to_ical()
+
+    cal2 = Calendar()
+    cal2.add_component(event2)
+    mock_event2 = MagicMock()
+    mock_event2.data = cal2.to_ical()
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = [mock_event1, mock_event2]
+
+    result = fetch_events(mock_calendar)
+
+    assert "good-event" in result
+    assert result["good-event"]["start"] is None
+    assert result["good-event"]["end"] is None
+
+
+def test_fetch_events_with_empty_fields():
+    """Test handling of events with empty optional fields."""
+    mock_event = create_mock_event(
+        uid="event-1",
+        summary="Event With Empty Fields",
+        start_time=datetime(2024, 1, 1, 10, 0, tzinfo=timezone.utc),
+        end_time=datetime(2024, 1, 1, 11, 0, tzinfo=timezone.utc),
+        description="",
+        location="",
+    )
+
+    mock_calendar = MagicMock()
+    mock_calendar.name = "Test Calendar"
+    mock_calendar.events.return_value = [mock_event]
+
+    result = fetch_events(mock_calendar)
+
+    assert len(result) == 1
+    event = result["event-1"]
+    assert event["description"] == ""
+    assert event["location"] == ""