Add comprehensive tests for conference module.
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ea712b2063
commit
88ccd79cb2
370
tests/test_conference.py
Normal file
370
tests/test_conference.py
Normal file
|
@ -0,0 +1,370 @@
|
|||
"""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)
|
Loading…
Reference in a new issue