"""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 = """
Weekdays | Monday 25 December 2023 |
Saturdays | Saturday 23 December 2023 |
Sundays | Sunday 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 = """
Weekdays | Monday 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 = """
Weekdays | Monday 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 = """
Weekdays | Monday 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 = """
Weekdays | Monday 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 = """
Weekdays | Tuesday 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)