import json import pytest from datetime import date, timedelta from room_cal.user_cal import UserCal from room_cal._utils import service_name as _service_name pytestmark = pytest.mark.usefixtures('require_user_cal') @pytest.mark.asyncio async def test_set_and_find_services_round_trip(): """Create a service event, read it back via find_services, then clean up.""" ucal = UserCal() service_key = 'airbnb' reservation_id = 'TEST-USERCAL-001' scan_start = date.today() - timedelta(days=60) checkin = scan_start checkout = scan_start + timedelta(days=3) try: await ucal.set(service_key, reservation_id, checkin, checkout) events = await ucal.find_services(checkin, checkout) match = next((e for e in events if json.loads(e.x_data).get('reservation_id') == reservation_id), None) assert match is not None, "Service event not found after set" data = json.loads(match.x_data) assert data['service_key'] == service_key assert data['reservation_id'] == reservation_id assert match.all_day assert match.start.date() == checkin assert match.end.date() == checkout # DTEND is exclusive; last included day is checkout - 1 svc_name = _service_name(service_key) assert match.title == svc_name assert match.description == f"{svc_name}: {reservation_id}" finally: events = await ucal.find_services(checkin, checkout) for e in events: try: if json.loads(e.x_data).get('reservation_id') == reservation_id: await ucal.delete(e) except (ValueError, TypeError): pass remaining = await ucal.find_services(checkin, checkout) leftover = [e for e in remaining if json.loads(e.x_data or '{}').get('reservation_id') == reservation_id] assert not leftover, "Service event still present after cleanup" @pytest.mark.asyncio async def test_set_is_idempotent(): """Calling set twice for the same reservation_id updates rather than duplicates.""" ucal = UserCal() service_key = 'airbnb' reservation_id = 'TEST-USERCAL-002' scan_start = date.today() - timedelta(days=50) checkin = scan_start checkout = scan_start + timedelta(days=2) try: await ucal.set(service_key, reservation_id, checkin, checkout) await ucal.set(service_key, reservation_id, checkin, checkout) events = await ucal.find_services(checkin, checkout) matches = [e for e in events if json.loads(e.x_data).get('reservation_id') == reservation_id] assert len(matches) == 1, f"Expected 1 event, found {len(matches)}" finally: events = await ucal.find_services(checkin, checkout) for e in events: try: if json.loads(e.x_data).get('reservation_id') == reservation_id: await ucal.delete(e) except (ValueError, TypeError): pass @pytest.mark.asyncio async def test_find_closed_returns_only_room_closed(): """find_closed only returns events titled 'Room Closed', not service events.""" ucal = UserCal() service_key = 'airbnb' reservation_id = 'TEST-USERCAL-003' scan_start = date.today() - timedelta(days=40) checkin = scan_start checkout = scan_start + timedelta(days=2) try: await ucal.set(service_key, reservation_id, checkin, checkout) closed_events = await ucal.find_closed(checkin, checkout) assert all(e.title == 'Room Closed' for e in closed_events), \ "find_closed returned an event that is not titled 'Room Closed'" service_events = await ucal.find_services(checkin, checkout) titles = {e.title for e in service_events} assert 'Room Closed' not in titles, "find_services returned a 'Room Closed' event" finally: events = await ucal.find_services(checkin, checkout) for e in events: try: if json.loads(e.x_data).get('reservation_id') == reservation_id: await ucal.delete(e) except (ValueError, TypeError): pass