test_user_cal.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import json
  2. import pytest
  3. from datetime import date, timedelta
  4. from room_cal.user_cal import UserCal
  5. from room_cal._utils import service_name as _service_name
  6. @pytest.mark.asyncio
  7. async def test_set_and_find_services_round_trip():
  8. """Create a service event, read it back via find_services, then clean up."""
  9. ucal = UserCal()
  10. service_key = 'airbnb'
  11. reservation_id = 'TEST-USERCAL-001'
  12. scan_start = date.today() - timedelta(days=60)
  13. checkin = scan_start
  14. checkout = scan_start + timedelta(days=3)
  15. try:
  16. await ucal.set(service_key, reservation_id, checkin, checkout)
  17. events = await ucal.find_services(checkin, checkout)
  18. match = next((e for e in events if json.loads(e['x_data']).get('reservation_id') == reservation_id), None)
  19. assert match is not None, "Service event not found after set"
  20. data = json.loads(match['x_data'])
  21. assert data['service_key'] == service_key
  22. assert data['reservation_id'] == reservation_id
  23. assert match['all_day']
  24. assert match['start'].date() == checkin
  25. assert match['end'].date() == checkout # DTEND is exclusive; last included day is checkout - 1
  26. svc_name = _service_name(service_key)
  27. assert match['title'] == svc_name
  28. assert match['description'] == f"{svc_name}: {reservation_id}"
  29. finally:
  30. events = await ucal.find_services(checkin, checkout)
  31. for e in events:
  32. try:
  33. if json.loads(e['x_data']).get('reservation_id') == reservation_id:
  34. await ucal.delete(e)
  35. except (ValueError, TypeError):
  36. pass
  37. remaining = await ucal.find_services(checkin, checkout)
  38. leftover = [e for e in remaining if json.loads(e.get('x_data') or '{}').get('reservation_id') == reservation_id]
  39. assert not leftover, "Service event still present after cleanup"
  40. @pytest.mark.asyncio
  41. async def test_set_is_idempotent():
  42. """Calling set twice for the same reservation_id updates rather than duplicates."""
  43. ucal = UserCal()
  44. service_key = 'airbnb'
  45. reservation_id = 'TEST-USERCAL-002'
  46. scan_start = date.today() - timedelta(days=50)
  47. checkin = scan_start
  48. checkout = scan_start + timedelta(days=2)
  49. try:
  50. await ucal.set(service_key, reservation_id, checkin, checkout)
  51. await ucal.set(service_key, reservation_id, checkin, checkout)
  52. events = await ucal.find_services(checkin, checkout)
  53. matches = [e for e in events if json.loads(e['x_data']).get('reservation_id') == reservation_id]
  54. assert len(matches) == 1, f"Expected 1 event, found {len(matches)}"
  55. finally:
  56. events = await ucal.find_services(checkin, checkout)
  57. for e in events:
  58. try:
  59. if json.loads(e['x_data']).get('reservation_id') == reservation_id:
  60. await ucal.delete(e)
  61. except (ValueError, TypeError):
  62. pass
  63. @pytest.mark.asyncio
  64. async def test_find_closed_returns_only_room_closed():
  65. """find_closed only returns events titled 'Room Closed', not service events."""
  66. ucal = UserCal()
  67. service_key = 'airbnb'
  68. reservation_id = 'TEST-USERCAL-003'
  69. scan_start = date.today() - timedelta(days=40)
  70. checkin = scan_start
  71. checkout = scan_start + timedelta(days=2)
  72. try:
  73. await ucal.set(service_key, reservation_id, checkin, checkout)
  74. closed_events = await ucal.find_closed(checkin, checkout)
  75. assert all(e['title'] == 'Room Closed' for e in closed_events), \
  76. "find_closed returned an event that is not titled 'Room Closed'"
  77. service_events = await ucal.find_services(checkin, checkout)
  78. titles = {e['title'] for e in service_events}
  79. assert 'Room Closed' not in titles, "find_services returned a 'Room Closed' event"
  80. finally:
  81. events = await ucal.find_services(checkin, checkout)
  82. for e in events:
  83. try:
  84. if json.loads(e['x_data']).get('reservation_id') == reservation_id:
  85. await ucal.delete(e)
  86. except (ValueError, TypeError):
  87. pass