agenda/tests/test_gwr.py
2025-07-20 01:11:07 +02:00

209 lines
7.4 KiB
Python

"""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 = """
<tr><td>Weekdays</td><td>Monday 25 December 2023</td></tr>
<tr><td>Saturdays</td><td>Saturday 23 December 2023</td></tr>
<tr><td>Sundays</td><td>Sunday 24 December 2023</td></tr>
"""
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 = """
<tr><td>Weekdays</td><td>Monday 25 December 2023**</td></tr>
"""
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 = "<p>No relevant table data here</p>"
result = extract_dates(html)
assert result is None
def test_extract_dates_whitespace_handling(self) -> None:
"""Test extracting dates with various whitespace."""
html = """
<tr> <td>Weekdays</td> <td>Monday 25 December 2023</td> </tr>
"""
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 = """
<tr><td>Weekdays</td><td>Monday 25 December 2023</td></tr>
"""
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 = """
<tr><td>Weekdays</td><td>Monday 25 December 2023**</td></tr>
"""
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 = "<p>No weekday data here</p>"
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 = """
<tr>
<td>Weekdays</td>
<td>Monday 25 December 2023</td>
</tr>
"""
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 = "<html>test content</html>"
# 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 = "<html>cached content</html>"
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 = "<html>fresh content</html>"
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 == "<html>fresh content</html>"
# 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 == "<html>fresh content</html>"
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 = """
<tr><td>Weekdays</td><td>Monday 25 December 2023</td></tr>
"""
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 = "<p>No relevant data</p>"
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 = """
<tr><td>Weekdays</td><td>Tuesday 26 December 2023</td></tr>
"""
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)