intermittent commit

This commit is contained in:
2026-07-14 13:22:10 +02:00
parent c071235ad7
commit 371a00aff5
8 changed files with 561 additions and 281 deletions

View File

@@ -2,7 +2,6 @@ from __future__ import annotations
import unittest
from datetime import datetime, timezone
from types import SimpleNamespace
from unittest.mock import patch
from sqlalchemy import create_engine
@@ -10,7 +9,7 @@ from sqlalchemy.orm import sessionmaker
from govoplan_access.backend.db import models as access_models # noqa: F401 - populate users/accounts tables
from govoplan_calendar.backend.caldav import CalDAVClient, CalDAVError, CalDAVNotFound, CalDAVObject, CalDAVPreconditionFailed, CalDAVReportResult, CalDAVWriteResult, parse_multistatus
from govoplan_calendar.backend.db.models import CalendarEvent, CalendarSyncCredential, CalendarSyncSource
from govoplan_calendar.backend.db.models import CalendarEvent, CalendarSyncCredential
from govoplan_calendar.backend.schemas import CalendarCalDavSourceCreateRequest, CalendarCollectionCreateRequest, CalendarEventCreateRequest, CalendarEventUpdateRequest
from govoplan_calendar.backend.service import (
CALDAV_INTERNAL_CREDENTIAL_PREFIX,
@@ -84,6 +83,14 @@ class FakeCalDAVClient:
return CalDAVWriteResult(href=href, status=204)
class FakeNotificationProvider:
def __init__(self) -> None:
self.requests: list[object] = []
def enqueue_notification(self, _session, request, **_kwargs) -> None:
self.requests.append(request)
class CalDAVParsingTests(unittest.TestCase):
def test_parse_multistatus_extracts_objects_sync_token_and_deletions(self) -> None:
result = parse_multistatus(
@@ -216,10 +223,8 @@ END:VCALENDAR</C:calendar-data>
self.assertEqual(calendars[0].collection_url, "https://cloud.example.test/remote.php/dav/calendars/ada/personal/")
def test_discovery_reports_relative_url_as_caldav_error(self) -> None:
client = CalDAVClient(collection_url="/remote.php/dav")
with self.assertRaisesRegex(CalDAVError, "unknown url type"):
client.discover_calendars()
with self.assertRaisesRegex(CalDAVError, "absolute HTTP"):
CalDAVClient(collection_url="/remote.php/dav")
class CalDAVSyncTests(unittest.TestCase):
@@ -359,6 +364,34 @@ class CalDAVSyncTests(unittest.TestCase):
next_sync_at = source.next_sync_at if source.next_sync_at.tzinfo else source.next_sync_at.replace(tzinfo=timezone.utc)
self.assertGreater(next_sync_at, datetime(2026, 7, 7, 8, 1, tzinfo=timezone.utc))
def test_due_sync_emits_recovery_notification_after_previous_error(self) -> None:
session = self.Session()
session.add(Tenant(id="tenant-1", slug="tenant-1", name="Tenant"))
calendar = create_calendar(session, tenant_id="tenant-1", user_id=None, payload=CalendarCollectionCreateRequest(name="Remote"))
source = create_caldav_source(
session,
tenant_id="tenant-1",
user_id=None,
payload=CalendarCalDavSourceCreateRequest(calendar_id=calendar.id, collection_url="https://dav.example.test/cal"),
)
source.last_status = "error"
source.next_sync_at = datetime(2026, 7, 7, 8, 0, tzinfo=timezone.utc)
session.commit()
provider = FakeNotificationProvider()
fake = FakeCalDAVClient(list_result=CalDAVReportResult(sync_token="token-1"))
with patch("govoplan_calendar.backend.service.notification_dispatch_provider", return_value=provider):
results = sync_due_caldav_sources(
session,
tenant_id="tenant-1",
now=datetime(2026, 7, 7, 8, 1, tzinfo=timezone.utc),
client_factory=lambda _source: fake,
)
self.assertEqual(results[0].status, "ok")
self.assertEqual(len(provider.requests), 1)
self.assertEqual(provider.requests[0].event_kind, "calendar.sync.ok")
def test_create_and_update_event_puts_caldav_resource_with_etag(self) -> None:
session = self.Session()
session.add(Tenant(id="tenant-1", slug="tenant-1", name="Tenant"))