"""Tests for agenda.conference module.""" import decimal import tempfile from datetime import date, datetime from typing import Any import pytest import yaml from agenda.conference import Conference, get_list from agenda.event import Event class TestConference: """Tests for Conference dataclass.""" def test_conference_creation_minimal(self) -> None: """Test creating conference with minimal required fields.""" conf = Conference( name="PyCon", topic="Python", location="Portland", start=date(2024, 5, 15), end=date(2024, 5, 17), ) assert conf.name == "PyCon" assert conf.topic == "Python" assert conf.location == "Portland" assert conf.start == date(2024, 5, 15) assert conf.end == date(2024, 5, 17) assert conf.trip is None assert conf.going is False assert conf.online is False def test_conference_creation_full(self) -> None: """Test creating conference with all fields.""" conf = Conference( name="PyCon US", topic="Python", location="Portland", start=date(2024, 5, 15), end=date(2024, 5, 17), trip=date(2024, 5, 14), country="USA", venue="Convention Center", address="123 Main St", url="https://pycon.org", accommodation_booked=True, transport_booked=True, going=True, registered=True, speaking=True, online=False, price=decimal.Decimal("500.00"), currency="USD", latitude=45.5152, longitude=-122.6784, cfp_end=date(2024, 2, 1), cfp_url="https://pycon.org/cfp", free=False, hackathon=True, ticket_type="early_bird", attendees=3000, hashtag="#pycon2024", ) assert conf.name == "PyCon US" assert conf.going is True assert conf.price == decimal.Decimal("500.00") assert conf.currency == "USD" assert conf.latitude == 45.5152 assert conf.longitude == -122.6784 assert conf.cfp_end == date(2024, 2, 1) assert conf.hashtag == "#pycon2024" def test_display_name_location_in_name(self) -> None: """Test display_name when location is already in conference name.""" conf = Conference( name="PyCon Portland", topic="Python", location="Portland", start=date(2024, 5, 15), end=date(2024, 5, 17), ) assert conf.display_name == "PyCon Portland" def test_display_name_location_not_in_name(self) -> None: """Test display_name when location is not in conference name.""" conf = Conference( name="PyCon", topic="Python", location="Portland", start=date(2024, 5, 15), end=date(2024, 5, 17), ) assert conf.display_name == "PyCon (Portland)" def test_display_name_partial_location_match(self) -> None: """Test display_name when location is partially in name.""" conf = Conference( name="PyConf", topic="Python", location="Conference Center", start=date(2024, 5, 15), end=date(2024, 5, 17), ) assert conf.display_name == "PyConf (Conference Center)" def test_conference_with_datetime(self) -> None: """Test conference with datetime objects.""" start_dt = datetime(2024, 5, 15, 9, 0) end_dt = datetime(2024, 5, 17, 17, 0) conf = Conference( name="PyCon", topic="Python", location="Portland", start=start_dt, end=end_dt, ) assert conf.start == start_dt assert conf.end == end_dt class TestGetList: """Tests for get_list function.""" def test_get_list_single_conference(self) -> None: """Test reading single conference from YAML.""" yaml_data = [ { "name": "PyCon", "topic": "Python", "location": "Portland", "start": date(2024, 5, 15), "end": date(2024, 5, 17), "url": "https://pycon.org", "going": True, } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 1 event = events[0] assert isinstance(event, Event) assert event.name == "conference" assert event.date == date(2024, 5, 15) assert event.end_date == date(2024, 5, 17) assert event.title == "PyCon (Portland)" assert event.url == "https://pycon.org" assert event.going is True def test_get_list_conference_with_cfp(self) -> None: """Test reading conference with CFP end date.""" yaml_data = [ { "name": "PyCon", "topic": "Python", "location": "Portland", "start": date(2024, 5, 15), "end": date(2024, 5, 17), "url": "https://pycon.org", "cfp_end": date(2024, 2, 1), "cfp_url": "https://pycon.org/cfp", } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 2 # Conference event conf_event = events[0] assert conf_event.name == "conference" assert conf_event.title == "PyCon (Portland)" assert conf_event.url == "https://pycon.org" # CFP end event cfp_event = events[1] assert cfp_event.name == "cfp_end" assert cfp_event.date == date(2024, 2, 1) assert cfp_event.title == "CFP end: PyCon (Portland)" assert cfp_event.url == "https://pycon.org/cfp" def test_get_list_conference_cfp_no_url(self) -> None: """Test reading conference with CFP end date but no CFP URL.""" yaml_data = [ { "name": "PyCon", "topic": "Python", "location": "Portland", "start": date(2024, 5, 15), "end": date(2024, 5, 17), "url": "https://pycon.org", "cfp_end": date(2024, 2, 1), } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 2 cfp_event = events[1] assert cfp_event.url == "https://pycon.org" # Falls back to conference URL def test_get_list_multiple_conferences(self) -> None: """Test reading multiple conferences from YAML.""" yaml_data = [ { "name": "PyCon", "topic": "Python", "location": "Portland", "start": date(2024, 5, 15), "end": date(2024, 5, 17), }, { "name": "EuroPython", "topic": "Python", "location": "Prague", "start": date(2024, 7, 8), "end": date(2024, 7, 14), "cfp_end": date(2024, 3, 15), }, ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 3 # 2 conferences + 1 CFP end # First conference assert events[0].title == "PyCon (Portland)" assert events[0].date == date(2024, 5, 15) # Second conference assert events[1].title == "EuroPython (Prague)" assert events[1].date == date(2024, 7, 8) # CFP end event for second conference assert events[2].name == "cfp_end" assert events[2].title == "CFP end: EuroPython (Prague)" def test_get_list_location_in_name(self) -> None: """Test conference where location is already in name.""" yaml_data = [ { "name": "PyCon Portland", "topic": "Python", "location": "Portland", "start": date(2024, 5, 15), "end": date(2024, 5, 17), } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 1 assert events[0].title == "PyCon Portland" # No location appended def test_get_list_datetime_objects(self) -> None: """Test reading conferences with datetime objects.""" yaml_data = [ { "name": "PyCon", "topic": "Python", "location": "Portland", "start": datetime(2024, 5, 15, 9, 0), "end": datetime(2024, 5, 17, 17, 0), } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 1 event = events[0] assert event.date == datetime(2024, 5, 15, 9, 0) assert event.end_date == datetime(2024, 5, 17, 17, 0) def test_get_list_invalid_date_order(self) -> None: """Test that conferences with end before start raise assertion error.""" yaml_data = [ { "name": "Invalid Conference", "topic": "Testing", "location": "Nowhere", "start": date(2024, 5, 17), "end": date(2024, 5, 15), # End before start } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() with pytest.raises(AssertionError): get_list(f.name) def test_get_list_too_long_conference(self) -> None: """Test that conferences longer than MAX_CONF_DAYS raise assertion error.""" yaml_data = [ { "name": "Too Long Conference", "topic": "Testing", "location": "Nowhere", "start": date(2024, 5, 1), "end": date(2024, 6, 1), # More than 20 days } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() with pytest.raises(AssertionError): get_list(f.name) def test_get_list_empty_file(self) -> None: """Test reading empty YAML file.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump([], f) f.flush() events = get_list(f.name) assert events == [] def test_get_list_same_day_conference(self) -> None: """Test conference that starts and ends on same day.""" yaml_data = [ { "name": "One Day Conference", "topic": "Testing", "location": "Test City", "start": date(2024, 5, 15), "end": date(2024, 5, 15), } ] with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: yaml.dump(yaml_data, f) f.flush() events = get_list(f.name) assert len(events) == 1 event = events[0] assert event.date == date(2024, 5, 15) assert event.end_date == date(2024, 5, 15)