"""Tests for agenda.gwr module.""" import os import tempfile from datetime import date from typing import Any from unittest.mock import AsyncMock, patch import pytest from agenda.gwr import ( advance_ticket_date, advance_tickets_page_html, extract_dates, extract_weekday_date, parse_date_string, ) class TestParseDateString: """Tests for parse_date_string function.""" def test_parse_date_with_year(self) -> None: """Test parsing date string with year included.""" result = parse_date_string("Monday 25 December 2023") assert result == date(2023, 12, 25) def test_parse_date_without_year(self) -> None: """Test parsing date string without year (should use current year).""" current_year = date.today().year result = parse_date_string("Monday 25 December") assert result == date(current_year, 12, 25) def test_parse_different_formats(self) -> None: """Test parsing various date formats.""" result = parse_date_string("Friday 1 January 2024") assert result == date(2024, 1, 1) result = parse_date_string("Saturday 29 February 2024") assert result == date(2024, 2, 29) class TestExtractDates: """Tests for extract_dates function.""" def test_extract_valid_dates(self) -> None: """Test extracting dates from valid HTML.""" html = """ WeekdaysMonday 25 December 2023 SaturdaysSaturday 23 December 2023 SundaysSunday 24 December 2023 """ result = extract_dates(html) expected = { "Weekdays": date(2023, 12, 25), "Saturdays": date(2023, 12, 23), "Sundays": date(2023, 12, 24), } assert result == expected def test_extract_dates_with_asterisks(self) -> None: """Test extracting dates when HTML contains asterisks.""" html = """ WeekdaysMonday 25 December 2023** """ result = extract_dates(html) expected = {"Weekdays": date(2023, 12, 25)} assert result == expected def test_extract_dates_no_match(self) -> None: """Test extracting dates when no pattern matches.""" html = "

No relevant table data here

" result = extract_dates(html) assert result is None def test_extract_dates_whitespace_handling(self) -> None: """Test extracting dates with various whitespace.""" html = """ Weekdays Monday 25 December 2023 """ result = extract_dates(html) expected = {"Weekdays": date(2023, 12, 25)} assert result == expected class TestExtractWeekdayDate: """Tests for extract_weekday_date function.""" def test_extract_valid_weekday_date(self) -> None: """Test extracting weekday date from valid HTML.""" html = """ WeekdaysMonday 25 December 2023 """ result = extract_weekday_date(html) assert result == date(2023, 12, 25) def test_extract_weekday_date_with_asterisks(self) -> None: """Test extracting weekday date when HTML contains asterisks.""" html = """ WeekdaysMonday 25 December 2023** """ result = extract_weekday_date(html) assert result == date(2023, 12, 25) def test_extract_weekday_date_no_match(self) -> None: """Test extracting weekday date when no pattern matches.""" html = "

No weekday data here

" result = extract_weekday_date(html) assert result is None def test_extract_weekday_date_multiline(self) -> None: """Test extracting weekday date with multiline content.""" html = """ Weekdays Monday 25 December 2023 """ result = extract_weekday_date(html) assert result == date(2023, 12, 25) class TestAdvanceTicketsPageHtml: """Tests for advance_tickets_page_html function.""" @pytest.mark.asyncio async def test_cache_hit(self) -> None: """Test using cached HTML when file is fresh.""" with tempfile.TemporaryDirectory() as temp_dir: cache_file = os.path.join(temp_dir, "advance-tickets.html") test_content = "test content" # Create a fresh cache file with open(cache_file, "w") as f: f.write(test_content) result = await advance_tickets_page_html(temp_dir, ttl=3600) assert result == test_content @pytest.mark.asyncio async def test_force_cache(self) -> None: """Test forcing cache usage even when file doesn't exist.""" with tempfile.TemporaryDirectory() as temp_dir: cache_file = os.path.join(temp_dir, "advance-tickets.html") test_content = "cached content" with open(cache_file, "w") as f: f.write(test_content) result = await advance_tickets_page_html(temp_dir, force_cache=True) assert result == test_content @pytest.mark.asyncio @patch("httpx.AsyncClient") async def test_fetch_from_web(self, mock_client: Any) -> None: """Test fetching from web when cache is stale.""" mock_response = AsyncMock() mock_response.text = "fresh content" mock_client.return_value.__aenter__.return_value.get.return_value = ( mock_response ) with tempfile.TemporaryDirectory() as temp_dir: result = await advance_tickets_page_html(temp_dir, ttl=0) assert result == "fresh content" # Check that content was cached cache_file = os.path.join(temp_dir, "advance-tickets.html") with open(cache_file) as f: cached_content = f.read() assert cached_content == "fresh content" class TestAdvanceTicketDate: """Tests for advance_ticket_date function.""" @pytest.mark.asyncio @patch("agenda.gwr.advance_tickets_page_html") async def test_advance_ticket_date_success(self, mock_html: Any) -> None: """Test successfully extracting advance ticket date.""" mock_html.return_value = """ WeekdaysMonday 25 December 2023 """ result = await advance_ticket_date("/fake/dir") assert result == date(2023, 12, 25) mock_html.assert_called_once_with("/fake/dir", force_cache=False) @pytest.mark.asyncio @patch("agenda.gwr.advance_tickets_page_html") async def test_advance_ticket_date_no_match(self, mock_html: Any) -> None: """Test when no weekday date can be extracted.""" mock_html.return_value = "

No relevant data

" result = await advance_ticket_date("/fake/dir") assert result is None @pytest.mark.asyncio @patch("agenda.gwr.advance_tickets_page_html") async def test_advance_ticket_date_force_cache(self, mock_html: Any) -> None: """Test advance_ticket_date with force_cache parameter.""" mock_html.return_value = """ WeekdaysTuesday 26 December 2023 """ result = await advance_ticket_date("/fake/dir", force_cache=True) assert result == date(2023, 12, 26) mock_html.assert_called_once_with("/fake/dir", force_cache=True)