test_user_cal.py 3.8 KB

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