Files
reflector/server/tests/test_attendee_parsing_bug.py
Mathieu Virbel 27b3b9cdee test: update test fixtures to use @with_session decorator
- Replace manual session management in test fixtures with @with_session decorator
- Simplify async test fixtures by removing explicit session handling
- Update dependencies in pyproject.toml and uv.lock
2025-09-23 12:09:26 -06:00

113 lines
3.7 KiB
Python

import os
from unittest.mock import patch
import pytest
from reflector.db.rooms import rooms_controller
from reflector.services.ics_sync import ICSSyncService
@pytest.mark.asyncio
async def test_attendee_parsing_bug(db_session):
"""
Test that reproduces the attendee parsing bug where a string with comma-separated
emails gets parsed as individual characters instead of separate email addresses.
The bug manifests as getting 29 attendees with emails like "M", "A", "I", etc.
instead of properly parsed email addresses.
"""
room = await rooms_controller.add(
db_session,
name="test-room",
user_id="test-user",
zulip_auto_post=False,
zulip_stream="",
zulip_topic="",
is_locked=False,
room_mode="normal",
recording_type="cloud",
recording_trigger="automatic-2nd-participant",
is_shared=False,
ics_url="http://test.com/test.ics",
ics_enabled=True,
)
await db_session.flush()
from datetime import datetime, timedelta, timezone
test_ics_path = os.path.join(
os.path.dirname(__file__), "test_attendee_parsing_bug.ics"
)
with open(test_ics_path, "r") as f:
ics_content = f.read()
now = datetime.now(timezone.utc)
future_time = now + timedelta(hours=1)
end_time = future_time + timedelta(hours=1)
dtstart = future_time.strftime("%Y%m%dT%H%M%SZ")
dtend = end_time.strftime("%Y%m%dT%H%M%SZ")
dtstamp = now.strftime("%Y%m%dT%H%M%SZ")
ics_content = ics_content.replace("20250910T180000Z", dtstart)
ics_content = ics_content.replace("20250910T190000Z", dtend)
ics_content = ics_content.replace("20250910T174000Z", dtstamp)
sync_service = ICSSyncService()
from contextlib import asynccontextmanager
from unittest.mock import AsyncMock
@asynccontextmanager
async def mock_session_context():
yield db_session
class MockSessionMaker:
def __call__(self):
return mock_session_context()
mock_session_factory = MockSessionMaker()
with patch("reflector.services.ics_sync.get_session_factory") as mock_get_factory:
mock_get_factory.return_value = mock_session_factory
with patch.object(
sync_service.fetch_service, "fetch_ics", new_callable=AsyncMock
) as mock_fetch:
mock_fetch.return_value = ics_content
calendar = sync_service.fetch_service.parse_ics(ics_content)
from reflector.settings import settings
room_url = f"{settings.UI_BASE_URL}/{room.name}"
print(f"Room URL being used for matching: {room_url}")
print(f"ICS content:\n{ics_content}")
events, total_events = sync_service.fetch_service.extract_room_events(
calendar, room.name, room_url
)
print(f"Total events in calendar: {total_events}")
print(f"Events matching room: {len(events)}")
result = await sync_service.sync_room_calendar(room)
assert result.get("status") == "success"
assert result.get("events_found", 0) >= 0
assert len(events) == 1
event = events[0]
attendees = event["attendees"]
print(f"Number of attendees: {len(attendees)}")
for i, attendee in enumerate(attendees):
print(f"Attendee {i}: {attendee}")
assert len(attendees) == 30, f"Expected 30 attendees, got {len(attendees)}"
assert attendees[0]["email"] == "alice@example.com"
assert attendees[1]["email"] == "bob@example.com"
assert attendees[2]["email"] == "charlie@example.com"
assert any(att["email"] == "organizer@example.com" for att in attendees)