diff --git a/tests/test_services_schedule.py b/tests/test_services_schedule.py index 134a978..70e60c7 100644 --- a/tests/test_services_schedule.py +++ b/tests/test_services_schedule.py @@ -9,43 +9,18 @@ asyncio.gather parallelization and post-fetch filtering logic. import pytest from unittest.mock import AsyncMock, patch -from models.game import Game -from models.team import Team from services.schedule_service import ScheduleService +from tests.factories import GameFactory, TeamFactory -def _make_team(team_id: int, abbrev: str) -> Team: - """Create a minimal Team for testing.""" - return Team( - id=team_id, - abbrev=abbrev, - sname=abbrev, - lname=f"{abbrev} Team", - season=12, - ) - - -def _make_game( - game_id: int, - week: int, - away_abbrev: str, - home_abbrev: str, - *, - away_score=None, - home_score=None, - game_num=1, -) -> Game: - """Create a Game with the given matchup and optional scores.""" - return Game( +def _game(game_id, week, away_abbrev, home_abbrev, **kwargs): + """Create a Game with distinct team IDs per matchup.""" + return GameFactory.create( id=game_id, - season=12, week=week, - game_num=game_num, - season_type="regular", - away_team=_make_team(game_id * 10, away_abbrev), - home_team=_make_team(game_id * 10 + 1, home_abbrev), - away_score=away_score, - home_score=home_score, + away_team=TeamFactory.create(id=game_id * 10, abbrev=away_abbrev), + home_team=TeamFactory.create(id=game_id * 10 + 1, abbrev=home_abbrev), + **kwargs, ) @@ -139,11 +114,11 @@ class TestGetTeamSchedule: """get_team_schedule returns only games involving the requested team, regardless of abbreviation casing.""" week1 = [ - _make_game(1, 1, "NYY", "BOS", away_score=3, home_score=1), - _make_game(2, 1, "LAD", "CHC", away_score=5, home_score=2), + _game(1, 1, "NYY", "BOS", away_score=3, home_score=1), + _game(2, 1, "LAD", "CHC", away_score=5, home_score=2), ] week2 = [ - _make_game(3, 2, "BOS", "NYY", away_score=2, home_score=4), + _game(3, 2, "BOS", "NYY", away_score=2, home_score=4), ] with patch.object(service, "get_week_schedule", new_callable=AsyncMock) as mock: @@ -151,8 +126,9 @@ class TestGetTeamSchedule: result = await service.get_team_schedule(12, "nyy", weeks=2) assert len(result) == 2 - abbrevs = {(g.away_team.abbrev, g.home_team.abbrev) for g in result} - assert all("NYY" in pair for pair in abbrevs) + assert all( + g.away_team.abbrev == "NYY" or g.home_team.abbrev == "NYY" for g in result + ) @pytest.mark.asyncio async def test_full_season_fetches_18_weeks(self, service): @@ -183,8 +159,8 @@ class TestGetRecentGames: @pytest.mark.asyncio async def test_returns_only_completed_games(self, service): """get_recent_games filters out games without scores.""" - completed = _make_game(1, 10, "NYY", "BOS", away_score=3, home_score=1) - incomplete = _make_game(2, 10, "LAD", "CHC") + completed = GameFactory.completed(id=1, week=10) + incomplete = GameFactory.upcoming(id=2, week=10) with patch.object(service, "get_week_schedule", new_callable=AsyncMock) as mock: mock.return_value = [completed, incomplete] @@ -196,10 +172,8 @@ class TestGetRecentGames: @pytest.mark.asyncio async def test_sorted_descending_by_week_and_game_num(self, service): """Recent games are sorted most-recent first.""" - game_w10 = _make_game( - 1, 10, "NYY", "BOS", away_score=3, home_score=1, game_num=2 - ) - game_w9 = _make_game(2, 9, "LAD", "CHC", away_score=5, home_score=2, game_num=1) + game_w10 = GameFactory.completed(id=1, week=10, game_num=2) + game_w9 = GameFactory.completed(id=2, week=9, game_num=1) with patch.object(service, "get_week_schedule", new_callable=AsyncMock) as mock: mock.side_effect = [[game_w10], [game_w9]] @@ -229,8 +203,8 @@ class TestGetUpcomingGames: @pytest.mark.asyncio async def test_returns_only_incomplete_games(self, service): """get_upcoming_games filters out completed games.""" - completed = _make_game(1, 5, "NYY", "BOS", away_score=3, home_score=1) - upcoming = _make_game(2, 5, "LAD", "CHC") + completed = GameFactory.completed(id=1, week=5) + upcoming = GameFactory.upcoming(id=2, week=5) with patch.object(service, "get_week_schedule", new_callable=AsyncMock) as mock: mock.return_value = [completed, upcoming] @@ -242,11 +216,11 @@ class TestGetUpcomingGames: @pytest.mark.asyncio async def test_sorted_ascending_by_week_and_game_num(self, service): """Upcoming games are sorted earliest first.""" - game_w3 = _make_game(1, 3, "NYY", "BOS", game_num=1) - game_w1 = _make_game(2, 1, "LAD", "CHC", game_num=2) + game_w3 = GameFactory.upcoming(id=1, week=3, game_num=1) + game_w1 = GameFactory.upcoming(id=2, week=1, game_num=2) with patch.object(service, "get_week_schedule", new_callable=AsyncMock) as mock: - # Week 1 returns game_w1, week 3 returns game_w3, others empty + def side_effect(season, week): if week == 1: return [game_w1] @@ -281,9 +255,9 @@ class TestGroupGamesBySeries: """Games between the same two teams are grouped under one key, with the alphabetically-first team first in the tuple.""" games = [ - _make_game(1, 1, "NYY", "BOS", game_num=1), - _make_game(2, 1, "BOS", "NYY", game_num=2), - _make_game(3, 1, "LAD", "CHC", game_num=1), + _game(1, 1, "NYY", "BOS", game_num=1), + _game(2, 1, "BOS", "NYY", game_num=2), + _game(3, 1, "LAD", "CHC", game_num=1), ] result = service.group_games_by_series(games) @@ -296,9 +270,9 @@ class TestGroupGamesBySeries: def test_sorted_by_game_num_within_series(self, service): """Games within each series are sorted by game_num.""" games = [ - _make_game(1, 1, "NYY", "BOS", game_num=3), - _make_game(2, 1, "NYY", "BOS", game_num=1), - _make_game(3, 1, "NYY", "BOS", game_num=2), + _game(1, 1, "NYY", "BOS", game_num=3), + _game(2, 1, "NYY", "BOS", game_num=1), + _game(3, 1, "NYY", "BOS", game_num=2), ] result = service.group_games_by_series(games)