agenda/tests/test_calendar.py
Edward Betts e6327780aa Add comprehensive test coverage for 8 modules
Increases overall test coverage from 53% to 56% by adding tests for:
- accommodation.py (60% → 100%)
- birthday.py (24% → 100%)
- calendar.py (19% → 100%)
- carnival.py (33% → 100%)
- domains.py (75% → 100%)
- events_yaml.py (50% → 96%)
- fx.py (14% → 21% for tested functions)
- sun.py (55% → 100%)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-20 11:39:49 +02:00

270 lines
9.7 KiB
Python

"""Tests for calendar functionality."""
from datetime import date, datetime, timedelta
from typing import Any
from agenda.calendar import build_events, colors, event_type_color_map
from agenda.event import Event
class TestEventTypeColorMap:
"""Test the event type color mapping."""
def test_event_type_color_map_contains_expected_types(self) -> None:
"""Test that color map contains expected event types."""
expected_types = {
"bank_holiday", "conference", "us_holiday",
"birthday", "waste_schedule"
}
assert set(event_type_color_map.keys()) == expected_types
def test_event_type_color_map_values_are_valid(self) -> None:
"""Test that all color values are valid color names."""
expected_colors = {
"success-subtle", "primary-subtle", "secondary-subtle",
"info-subtle", "danger-subtle"
}
assert set(event_type_color_map.values()).issubset(expected_colors)
class TestColorsDict:
"""Test the colors dictionary."""
def test_colors_contains_expected_keys(self) -> None:
"""Test that colors dict contains expected color keys."""
expected_keys = {
"primary-subtle", "secondary-subtle", "success-subtle",
"info-subtle", "warning-subtle", "danger-subtle"
}
assert set(colors.keys()) == expected_keys
def test_colors_values_are_hex_codes(self) -> None:
"""Test that all color values are valid hex codes."""
for color_value in colors.values():
assert color_value.startswith("#")
assert len(color_value) == 7
# Check that remaining characters are valid hex
hex_part = color_value[1:]
int(hex_part, 16) # This will raise ValueError if not valid hex
class TestBuildEvents:
"""Test the build_events function."""
def test_build_events_empty_list(self) -> None:
"""Test building events with empty list."""
result = build_events([])
assert result == []
def test_build_events_today_event_filtered(self) -> None:
"""Test that 'today' events are filtered out."""
events = [
Event(date=date(2024, 1, 1), name="today", title="Today"),
Event(date=date(2024, 1, 2), name="birthday", title="Birthday"),
]
result = build_events(events)
assert len(result) == 1
assert result[0]["title"] == "🎈 Birthday"
def test_build_events_simple_event(self) -> None:
"""Test building a simple event without time."""
events = [
Event(
date=date(2024, 1, 15),
name="birthday",
title="John's Birthday"
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert item["allDay"] is True
assert item["title"] == "🎈 John's Birthday"
assert item["start"] == "2024-01-15"
assert item["end"] == "2024-01-16" # Next day
assert item["color"] == colors["info-subtle"]
assert item["textColor"] == "black"
def test_build_events_with_time(self) -> None:
"""Test building an event with time."""
event_datetime = datetime(2024, 1, 15, 14, 30)
events = [
Event(
date=event_datetime,
name="meeting",
title="Team Meeting"
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert item["allDay"] is False
assert item["title"] == "Team Meeting"
assert item["start"] == "2024-01-15T14:30:00"
assert item["end"] == "2024-01-15T15:00:00" # 30 minutes later
def test_build_events_with_end_date(self) -> None:
"""Test building an event with end date."""
events = [
Event(
date=date(2024, 1, 15),
name="conference",
title="Tech Conference",
end_date=date(2024, 1, 17)
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert item["allDay"] is True
assert item["start"] == "2024-01-15"
assert item["end"] == "2024-01-18" # End date + 1 day
def test_build_events_with_time_and_end_date(self) -> None:
"""Test building an event with time and end date."""
start_datetime = datetime(2024, 1, 15, 9, 0)
end_datetime = datetime(2024, 1, 15, 17, 0)
events = [
Event(
date=start_datetime,
name="workshop",
title="Python Workshop",
end_date=end_datetime
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert item["allDay"] is False
assert item["start"] == "2024-01-15T09:00:00"
assert item["end"] == "2024-01-15T17:00:00"
def test_build_events_with_url(self) -> None:
"""Test building an event with URL."""
events = [
Event(
date=date(2024, 1, 15),
name="conference",
title="Tech Conference",
url="https://example.com"
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert item["url"] == "https://example.com"
def test_build_events_accommodation(self) -> None:
"""Test building accommodation events."""
events = [
Event(
date=datetime(2024, 1, 15, 15, 0), # Check-in time
name="accommodation",
title="Hotel Stay",
end_date=datetime(2024, 1, 17, 11, 0), # Check-out time
url="https://hotel.com"
)
]
result = build_events(events)
# Should create 3 events: main accommodation + check-in + check-out
assert len(result) == 3
# Main accommodation event
main_event = result[0]
assert main_event["allDay"] is True
assert main_event["title"] == "🏨 Hotel Stay"
assert main_event["start"] == "2024-01-15"
assert main_event["end"] == "2024-01-18" # End date + 1 day
assert main_event["url"] == "https://hotel.com"
# Check-in event
checkin_event = result[1]
assert checkin_event["allDay"] is False
assert checkin_event["title"] == "check-in: Hotel Stay"
assert checkin_event["start"] == "2024-01-15T15:00:00"
assert checkin_event["url"] == "https://hotel.com"
# Check-out event
checkout_event = result[2]
assert checkout_event["allDay"] is False
assert checkout_event["title"] == "checkout: Hotel Stay"
assert checkout_event["start"] == "2024-01-17T11:00:00"
assert checkout_event["url"] == "https://hotel.com"
def test_build_events_no_color_for_unknown_type(self) -> None:
"""Test that events with unknown types don't get color."""
events = [
Event(
date=date(2024, 1, 15),
name="unknown_type",
title="Unknown Event"
)
]
result = build_events(events)
assert len(result) == 1
item = result[0]
assert "color" not in item
assert "textColor" not in item
def test_build_events_multiple_event_types(self) -> None:
"""Test building events with different types and colors."""
events = [
Event(date=date(2024, 1, 15), name="bank_holiday", title="New Year"),
Event(date=date(2024, 1, 16), name="conference", title="PyCon"),
Event(date=date(2024, 1, 17), name="birthday", title="Birthday"),
Event(date=date(2024, 1, 18), name="waste_schedule", title="Recycling"),
Event(date=date(2024, 1, 19), name="us_holiday", title="MLK Day"),
]
result = build_events(events)
assert len(result) == 5
# Check colors are assigned correctly
assert result[0]["color"] == colors["success-subtle"] # bank_holiday
assert result[1]["color"] == colors["primary-subtle"] # conference
assert result[2]["color"] == colors["info-subtle"] # birthday
assert result[3]["color"] == colors["danger-subtle"] # waste_schedule
assert result[4]["color"] == colors["secondary-subtle"] # us_holiday
# All should have black text
for item in result:
assert item["textColor"] == "black"
def test_build_events_mixed_scenarios(self) -> None:
"""Test building events with mixed scenarios."""
events = [
# Today event (should be filtered)
Event(date=date(2024, 1, 1), name="today", title="Today"),
# Simple event
Event(date=date(2024, 1, 15), name="birthday", title="Birthday"),
# Event with time
Event(date=datetime(2024, 1, 16, 10, 0), name="meeting", title="Meeting"),
# Accommodation
Event(
date=datetime(2024, 1, 20, 15, 0),
name="accommodation",
title="Hotel",
end_date=datetime(2024, 1, 22, 11, 0),
url="https://hotel.com"
),
]
result = build_events(events)
# Should have 5 events total (today filtered, accommodation creates 3)
assert len(result) == 5
# Verify titles
titles = [item["title"] for item in result]
assert "🎈 Birthday" in titles
assert "Meeting" in titles
assert "🏨 Hotel" in titles
assert "check-in: Hotel" in titles
assert "checkout: Hotel" in titles