"""Unit tests for calendar email detection and ICS parsing.""" import pytest from src.mail.utils.calendar_parser import ( parse_ics_content, parse_calendar_from_raw_message, extract_ics_from_mime, is_cancelled_event, is_event_request, ParsedCalendarEvent, ) from src.mail.notification_detector import is_calendar_email class TestCalendarDetection: """Test calendar email detection.""" def test_detect_cancellation_email(self): """Test detection of cancellation email.""" envelope = { "from": {"addr": "organizer@example.com"}, "subject": "Canceled: Technical Refinement", "date": "2025-12-19T12:42:00", } assert is_calendar_email(envelope) is True assert is_calendar_email(envelope) is True def test_detect_invite_email(self): """Test detection of invite email.""" envelope = { "from": {"addr": "organizer@example.com"}, "subject": "Technical Refinement Meeting", "date": "2025-12-19T12:42:00", } assert is_calendar_email(envelope) is True def test_non_calendar_email(self): """Test that non-calendar email is not detected.""" envelope = { "from": {"addr": "user@example.com"}, "subject": "Hello from a friend", "date": "2025-12-19T12:42:00", } assert is_calendar_email(envelope) is False class TestICSParsing: """Test ICS file parsing.""" def test_parse_cancellation_ics(self): """Test parsing of cancellation ICS.""" ics_content = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Test//Test//EN METHOD:CANCEL BEGIN:VEVENT UID:test-uid-001 SUMMARY:Technical Refinement Meeting DTSTART:20251230T140000Z DTEND:20251230T150000Z STATUS:CANCELLED ORGANIZER;CN=Test Organizer:mailto:organizer@example.com ATTENDEE;CN=Test Attendee:mailto:attendee@example.com END:VEVENT END:VCALENDAR""" event = parse_ics_content(ics_content) assert event is not None assert is_cancelled_event(event) is True assert event.method == "CANCEL" assert event.summary == "Technical Refinement Meeting" def test_parse_invite_ics(self): """Test parsing of invite/request ICS.""" ics_content = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Test//Test//EN METHOD:REQUEST BEGIN:VEVENT UID:test-uid-002 SUMMARY:Team Standup DTSTART:20251230T100000Z DTEND:20251230T103000Z STATUS:CONFIRMED ORGANIZER;CN=Test Organizer:mailto:organizer@example.com ATTENDEE;CN=Test Attendee:mailto:attendee@example.com LOCATION:Conference Room A END:VEVENT END:VCALENDAR""" event = parse_ics_content(ics_content) assert event is not None assert is_event_request(event) is True assert event.method == "REQUEST" assert event.summary == "Team Standup" assert event.location == "Conference Room A" def test_invalid_ics(self): """Test parsing of invalid ICS content.""" event = parse_ics_content("invalid ics content") assert event is None # Should return None for invalid ICS def test_extract_ics_from_mime(self): """Test extraction of ICS from raw MIME message.""" raw_message = """From: organizer@example.com To: attendee@example.com Subject: Meeting Invite Content-Type: multipart/mixed; boundary="boundary123" --boundary123 Content-Type: text/plain You have been invited to a meeting. --boundary123 Content-Type: text/calendar BEGIN:VCALENDAR VERSION:2.0 METHOD:REQUEST BEGIN:VEVENT UID:mime-test-001 SUMMARY:MIME Test Meeting DTSTART:20251230T140000Z DTEND:20251230T150000Z END:VEVENT END:VCALENDAR --boundary123-- """ ics = extract_ics_from_mime(raw_message) assert ics is not None assert "BEGIN:VCALENDAR" in ics assert "MIME Test Meeting" in ics event = parse_ics_content(ics) assert event is not None assert event.summary == "MIME Test Meeting" assert event.method == "REQUEST"