"""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