diff --git a/.secrets.baseline b/.secrets.baseline index 7cb5390..6ea4938 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -156,7 +156,7 @@ "filename": "tests/unit/test_caldav_gateway.py", "hashed_secret": "1c58bd92003bbaa0538e249fff6ee19a270dec5f", "is_verified": false, - "line_number": 763 + "line_number": 794 } ], "tests/unit/test_caldav_security.py": [ @@ -185,5 +185,5 @@ } ] }, - "generated_at": "2026-09-12T17:57:39Z" + "generated_at": "2026-09-12T22:12:56Z" } diff --git a/pronote_sync/sync/caldav.py b/pronote_sync/sync/caldav.py index 5ad6c60..4839a3d 100644 --- a/pronote_sync/sync/caldav.py +++ b/pronote_sync/sync/caldav.py @@ -191,7 +191,11 @@ class CalDAVGateway: for vevent in component.walk("VEVENT"): managed = vevent.get(MANAGED_PROPERTY) if managed is not None and str(managed) == MANAGED_VALUE: - raw_uid = str(vevent.get("UID")) + raw_uid_value = vevent.get("UID") + if raw_uid_value is None or not str(raw_uid_value).strip(): + logger.warning("Événement CalDAV géré sans UID ignoré.") + continue + raw_uid = str(raw_uid_value) canonical_uid = normalize_pronote_uid(raw_uid) result.append((raw_uid, canonical_uid, vevent)) except Exception as exc: diff --git a/tests/unit/test_caldav_gateway.py b/tests/unit/test_caldav_gateway.py index f6088a4..abcbd27 100644 --- a/tests/unit/test_caldav_gateway.py +++ b/tests/unit/test_caldav_gateway.py @@ -327,6 +327,37 @@ def test_list_managed_events_returns_only_managed( assert str(vevent.get("UID")) == "test-uid-123" +def test_list_managed_events_ignores_managed_event_without_uid( + caldav_settings: CalDAVSettings, + mock_client_factory: MagicMock, + caplog: LogCaptureFixture, +) -> None: + """Ignore un événement géré sans UID et ne le transmet pas au planificateur. + + :param caldav_settings: Paramètres CalDAV valides. + :param mock_client_factory: Usine de clients CalDAV mockée. + :param caplog: Capture des journaux de diagnostic. + :return: None + """ + gateway = CalDAVGateway(caldav_settings, client_factory=mock_client_factory) + gateway.connect() + + malformed_event = Event() + malformed_event.add("SUMMARY", "Événement sans identifiant") + malformed_event.add(MANAGED_PROPERTY, MANAGED_VALUE) + remote_event = MagicMock() + remote_event.icalendar_component = Calendar() + remote_event.icalendar_component.add_component(malformed_event) + calendar = mock_client_factory.return_value.principal.return_value.calendars.return_value[0] + calendar.search.return_value = [remote_event] + + with caplog.at_level(logging.WARNING): + result = gateway.list_managed_events(datetime(2026, 1, 1), datetime(2026, 12, 31)) + + assert result == [] + assert "sans UID ignoré" in caplog.text + + def test_list_managed_events_not_connected_raises( caldav_settings: CalDAVSettings, ) -> None: