from __future__ import annotations import tempfile import unittest from datetime import date, timedelta from pathlib import Path from hockey_data.client import Stat2TVNotFoundError, Stat2TVResponse from hockey_data.config import HockeySettingsStore from hockey_data.models import Tournament from hockey_data.service import HockeyDataService from support import LocalTestDatabase class TournamentScheduleFallbackTests(unittest.IsolatedAsyncioTestCase): async def test_missing_live_schedule_uses_tournament_scoped_fallback(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: base_dir = Path(temp_dir) database = LocalTestDatabase(base_dir / "test.sqlite3") database.create_all() settings = HockeySettingsStore(base_dir / "settings") service = HockeyDataService(base_dir=base_dir, database=database, settings=settings) today = date.today() tomorrow = today + timedelta(days=1) with database.session() as session: session.add(Tournament( external_id="1437", name_ru="Предсезонные матчи КХЛ", season="2026-2027", start_date=today - timedelta(days=5), end_date=today + timedelta(days=20), )) calls: list[str] = [] fallback_xml = f''' '''.encode("utf-8") async def fake_fetch(endpoint: str) -> Stat2TVResponse: calls.append(endpoint) if endpoint == "1437/schedule-1437-live.xml": raise Stat2TVNotFoundError("https://example.test/live", 404) if endpoint == "1437/schedule-1437.xml": return Stat2TVResponse( content=fallback_xml, status_code=200, content_type="application/xml", auth_mode="test", url=f"https://example.test/{endpoint}", ) raise Stat2TVNotFoundError(f"https://example.test/{endpoint}", 404) service.client.fetch_xml = fake_fetch # type: ignore[method-assign] result = await service.sync_games(tournament_external_id="1437", on_date=today) self.assertTrue(result["fallback_used"]) self.assertEqual(result["selected_date_count"], 1) self.assertEqual(result["endpoint"], "1437/schedule-1437.xml") self.assertEqual(calls[:2], [ "1437/schedule-1437-live.xml", "1437/schedule-1437.xml", ]) payload = service.games(tournament_external_id="1437", on_date=today) self.assertEqual(payload["meta"]["count"], 1) self.assertEqual(payload["items"][0]["external_id"], "902918") database.engine.dispose() if __name__ == "__main__": unittest.main() class TournamentScheduleDateQueryFallbackTests(unittest.IsolatedAsyncioTestCase): async def test_automatic_sync_reaches_root_date_query_candidates(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: base_dir = Path(temp_dir) database = LocalTestDatabase(base_dir / "test.sqlite3") database.create_all() settings = HockeySettingsStore(base_dir / "settings") service = HockeyDataService(base_dir=base_dir, database=database, settings=settings) selected = date(2026, 8, 12) with database.session() as session: session.add(Tournament( external_id="1437", name_ru="Предсезонные матчи КХЛ", season="2026-2027", start_date=date(2026, 7, 20), end_date=date(2026, 9, 4), )) calls: list[str] = [] payload = f''' '''.encode("utf-8") target = f"games.xml?tournament=1437&date={selected.isoformat()}" async def fake_fetch(endpoint: str) -> Stat2TVResponse: calls.append(endpoint) if endpoint == target: return Stat2TVResponse( content=payload, status_code=200, content_type="application/xml", auth_mode="test", url=f"https://example.test/{endpoint}", ) raise Stat2TVNotFoundError(f"https://example.test/{endpoint}", 404) service.client.fetch_xml = fake_fetch # type: ignore[method-assign] result = await service.sync_games( tournament_external_id="1437", on_date=selected, force_discovery=False, ) self.assertTrue(result["fallback_used"]) self.assertEqual(result["selected_date_count"], 1) self.assertEqual(result["endpoint"], target) self.assertIn(target, calls) # Confirm this happened during the normal automatic path, not only # force_discovery=True. self.assertGreater(calls.index(target), 0) visible = service.games(tournament_external_id="1437", on_date=selected) self.assertEqual(visible["meta"]["count"], 1) self.assertEqual(visible["items"][0]["external_id"], "902918") database.engine.dispose()