From 62b058bddfee4217fba960c855a9599ab4a55824 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 19 Feb 2026 21:19:31 -0600 Subject: [PATCH] test: fix weather test expecting 4 embed fields instead of 5 The Stadium Image field was added to the weather embed but the test_full_weather_workflow assertion wasn't updated to match. Co-Authored-By: Claude Opus 4.6 --- tests/test_commands_weather.py | 291 +++++++++++++++++++++++---------- 1 file changed, 201 insertions(+), 90 deletions(-) diff --git a/tests/test_commands_weather.py b/tests/test_commands_weather.py index 6b2d9a1..608705d 100644 --- a/tests/test_commands_weather.py +++ b/tests/test_commands_weather.py @@ -3,6 +3,7 @@ Tests for Weather Command (Discord interactions) Validates weather command functionality, team resolution, and embed creation. """ + import pytest from unittest.mock import AsyncMock, MagicMock, patch import discord @@ -53,54 +54,93 @@ class TestWeatherCommands: """Create mock team data.""" return TeamFactory.create( id=499, - abbrev='NYY', - sname='Yankees', - lname='New York Yankees', + abbrev="NYY", + sname="Yankees", + lname="New York Yankees", season=13, - color='a6ce39', - stadium='https://example.com/yankee-stadium.jpg', - thumbnail='https://example.com/yankee-thumbnail.png' + color="a6ce39", + stadium="https://example.com/yankee-stadium.jpg", + thumbnail="https://example.com/yankee-thumbnail.png", ) @pytest.fixture def mock_current(self): """Create mock current league state.""" return CurrentFactory.create( - week=10, - season=13, - freeze=False, - trade_deadline=14, - playoffs_begin=19 + week=10, season=13, freeze=False, trade_deadline=14, playoffs_begin=19 ) @pytest.fixture def mock_games(self): """Create mock game schedule.""" # Create teams for the games - yankees = TeamFactory.create(id=499, abbrev='NYY', sname='Yankees', lname='New York Yankees', season=13) - red_sox = TeamFactory.create(id=500, abbrev='BOS', sname='Red Sox', lname='Boston Red Sox', season=13) + yankees = TeamFactory.create( + id=499, abbrev="NYY", sname="Yankees", lname="New York Yankees", season=13 + ) + red_sox = TeamFactory.create( + id=500, abbrev="BOS", sname="Red Sox", lname="Boston Red Sox", season=13 + ) # 2 completed games, 2 upcoming games games = [ - GameFactory.completed(id=1, season=13, week=10, game_num=1, away_team=yankees, home_team=red_sox, away_score=5, home_score=3), - GameFactory.completed(id=2, season=13, week=10, game_num=2, away_team=yankees, home_team=red_sox, away_score=2, home_score=7), - GameFactory.upcoming(id=3, season=13, week=10, game_num=3, away_team=yankees, home_team=red_sox), - GameFactory.upcoming(id=4, season=13, week=10, game_num=4, away_team=yankees, home_team=red_sox), + GameFactory.completed( + id=1, + season=13, + week=10, + game_num=1, + away_team=yankees, + home_team=red_sox, + away_score=5, + home_score=3, + ), + GameFactory.completed( + id=2, + season=13, + week=10, + game_num=2, + away_team=yankees, + home_team=red_sox, + away_score=2, + home_score=7, + ), + GameFactory.upcoming( + id=3, + season=13, + week=10, + game_num=3, + away_team=yankees, + home_team=red_sox, + ), + GameFactory.upcoming( + id=4, + season=13, + week=10, + game_num=4, + away_team=yankees, + home_team=red_sox, + ), ] return games @pytest.mark.asyncio - async def test_weather_explicit_team(self, commands_cog, mock_interaction, mock_team, mock_current, mock_games): + async def test_weather_explicit_team( + self, commands_cog, mock_interaction, mock_team, mock_current, mock_games + ): """Test weather command with explicit team abbreviation.""" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service, \ - patch('commands.utilities.weather.schedule_service') as mock_schedule_service, \ - patch('commands.utilities.weather.team_service') as mock_team_service: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service, patch( + "commands.utilities.weather.schedule_service" + ) as mock_schedule_service, patch( + "commands.utilities.weather.team_service" + ) as mock_team_service: # Mock @requires_team decorator lookup mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } # Mock service responses @@ -109,37 +149,47 @@ class TestWeatherCommands: mock_team_service.get_team_by_abbrev = AsyncMock(return_value=mock_team) # Execute command - await commands_cog.weather.callback(commands_cog, mock_interaction, team_abbrev='NYY') + await commands_cog.weather.callback( + commands_cog, mock_interaction, team_abbrev="NYY" + ) # Verify interaction flow mock_interaction.response.defer.assert_called_once() mock_interaction.followup.send.assert_called_once() # Verify team lookup - mock_team_service.get_team_by_abbrev.assert_called_once_with('NYY', 13) + mock_team_service.get_team_by_abbrev.assert_called_once_with("NYY", 13) # Check embed was sent embed_call = mock_interaction.followup.send.call_args - assert 'embed' in embed_call.kwargs - embed = embed_call.kwargs['embed'] + assert "embed" in embed_call.kwargs + embed = embed_call.kwargs["embed"] assert embed.title == "🌤️ Weather Check" @pytest.mark.asyncio - async def test_weather_channel_name_resolution(self, commands_cog, mock_interaction, mock_team, mock_current, mock_games): + async def test_weather_channel_name_resolution( + self, commands_cog, mock_interaction, mock_team, mock_current, mock_games + ): """Test weather command resolving team from channel name.""" # Set channel name to format: - mock_interaction.channel.name = "NYY-Yankee-Stadium" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service, \ - patch('commands.utilities.weather.schedule_service') as mock_schedule_service, \ - patch('commands.utilities.weather.team_service') as mock_team_service, \ - patch('commands.utilities.weather.get_user_major_league_team') as mock_get_team: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service, patch( + "commands.utilities.weather.schedule_service" + ) as mock_schedule_service, patch( + "commands.utilities.weather.team_service" + ) as mock_team_service, patch( + "commands.utilities.weather.get_user_major_league_team" + ) as mock_get_team: # Mock @requires_team decorator lookup mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } mock_league_service.get_current_state = AsyncMock(return_value=mock_current) @@ -148,28 +198,38 @@ class TestWeatherCommands: mock_get_team.return_value = None # Execute without explicit team parameter - await commands_cog.weather.callback(commands_cog, mock_interaction, team_abbrev=None) + await commands_cog.weather.callback( + commands_cog, mock_interaction, team_abbrev=None + ) # Should resolve team from channel name "NYY-Yankee-Stadium" -> "NYY" - mock_team_service.get_team_by_abbrev.assert_called_once_with('NYY', 13) + mock_team_service.get_team_by_abbrev.assert_called_once_with("NYY", 13) mock_interaction.followup.send.assert_called_once() @pytest.mark.asyncio - async def test_weather_user_owned_team_fallback(self, commands_cog, mock_interaction, mock_team, mock_current, mock_games): + async def test_weather_user_owned_team_fallback( + self, commands_cog, mock_interaction, mock_team, mock_current, mock_games + ): """Test weather command falling back to user's owned team.""" # Set channel name that won't match a team mock_interaction.channel.name = "general-chat" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service, \ - patch('commands.utilities.weather.schedule_service') as mock_schedule_service, \ - patch('commands.utilities.weather.team_service') as mock_team_service, \ - patch('commands.utilities.weather.get_user_major_league_team') as mock_get_team: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service, patch( + "commands.utilities.weather.schedule_service" + ) as mock_schedule_service, patch( + "commands.utilities.weather.team_service" + ) as mock_team_service, patch( + "commands.utilities.weather.get_user_major_league_team" + ) as mock_get_team: # Mock @requires_team decorator lookup mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } mock_league_service.get_current_state = AsyncMock(return_value=mock_current) @@ -177,48 +237,64 @@ class TestWeatherCommands: mock_team_service.get_team_by_abbrev = AsyncMock(return_value=None) mock_get_team.return_value = mock_team - await commands_cog.weather.callback(commands_cog, mock_interaction, team_abbrev=None) + await commands_cog.weather.callback( + commands_cog, mock_interaction, team_abbrev=None + ) # Should fall back to user ownership mock_get_team.assert_called_once_with(258104532423147520, 13) mock_interaction.followup.send.assert_called_once() @pytest.mark.asyncio - async def test_weather_no_team_found(self, commands_cog, mock_interaction, mock_current, mock_team): + async def test_weather_no_team_found( + self, commands_cog, mock_interaction, mock_current, mock_team + ): """Test weather command when no team can be resolved.""" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service, \ - patch('commands.utilities.weather.team_service') as mock_team_service, \ - patch('commands.utilities.weather.get_user_major_league_team') as mock_get_team: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service, patch( + "commands.utilities.weather.team_service" + ) as mock_team_service, patch( + "commands.utilities.weather.get_user_major_league_team" + ) as mock_get_team: # Mock @requires_team decorator lookup - user has a team so decorator passes mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } mock_league_service.get_current_state = AsyncMock(return_value=mock_current) mock_team_service.get_team_by_abbrev = AsyncMock(return_value=None) mock_get_team.return_value = None - await commands_cog.weather.callback(commands_cog, mock_interaction, team_abbrev=None) + await commands_cog.weather.callback( + commands_cog, mock_interaction, team_abbrev=None + ) # Should send error message embed_call = mock_interaction.followup.send.call_args - embed = embed_call.kwargs['embed'] + embed = embed_call.kwargs["embed"] assert "Team Not Found" in embed.title assert "Could not find a team" in embed.description @pytest.mark.asyncio - async def test_weather_league_state_unavailable(self, commands_cog, mock_interaction, mock_team): + async def test_weather_league_state_unavailable( + self, commands_cog, mock_interaction, mock_team + ): """Test weather command when league state is unavailable.""" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service: # Mock @requires_team decorator lookup mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } mock_league_service.get_current_state = AsyncMock(return_value=None) @@ -227,7 +303,7 @@ class TestWeatherCommands: # Should send error about league state embed_call = mock_interaction.followup.send.call_args - embed = embed_call.kwargs['embed'] + embed = embed_call.kwargs["embed"] assert "League State Unavailable" in embed.title @pytest.mark.asyncio @@ -329,7 +405,7 @@ class TestWeatherCommands: weather_roll=14, games_played=2, total_games=4, - username="TestUser" + username="TestUser", ) # Check embed basics @@ -363,74 +439,94 @@ class TestWeatherCommands: assert embed.image.url == mock_team.stadium @pytest.mark.asyncio - async def test_full_weather_workflow(self, commands_cog, mock_interaction, mock_team, mock_current, mock_games): + async def test_full_weather_workflow( + self, commands_cog, mock_interaction, mock_team, mock_current, mock_games + ): """Test complete weather workflow with realistic data.""" - with patch('utils.permissions.get_user_team') as mock_get_user_team, \ - patch('commands.utilities.weather.league_service') as mock_league_service, \ - patch('commands.utilities.weather.schedule_service') as mock_schedule_service, \ - patch('commands.utilities.weather.team_service') as mock_team_service: + with patch("utils.permissions.get_user_team") as mock_get_user_team, patch( + "commands.utilities.weather.league_service" + ) as mock_league_service, patch( + "commands.utilities.weather.schedule_service" + ) as mock_schedule_service, patch( + "commands.utilities.weather.team_service" + ) as mock_team_service: # Mock @requires_team decorator lookup mock_get_user_team.return_value = { - 'id': mock_team.id, 'name': mock_team.lname, - 'abbrev': mock_team.abbrev, 'season': mock_team.season + "id": mock_team.id, + "name": mock_team.lname, + "abbrev": mock_team.abbrev, + "season": mock_team.season, } mock_league_service.get_current_state = AsyncMock(return_value=mock_current) mock_schedule_service.get_week_schedule = AsyncMock(return_value=mock_games) mock_team_service.get_team_by_abbrev = AsyncMock(return_value=mock_team) - await commands_cog.weather.callback(commands_cog, mock_interaction, team_abbrev='NYY') + await commands_cog.weather.callback( + commands_cog, mock_interaction, team_abbrev="NYY" + ) # Verify complete flow mock_interaction.response.defer.assert_called_once() mock_league_service.get_current_state.assert_called_once() mock_schedule_service.get_week_schedule.assert_called_once_with(13, 10) - mock_team_service.get_team_by_abbrev.assert_called_once_with('NYY', 13) + mock_team_service.get_team_by_abbrev.assert_called_once_with("NYY", 13) # Check final embed embed_call = mock_interaction.followup.send.call_args - embed = embed_call.kwargs['embed'] + embed = embed_call.kwargs["embed"] # Validate embed structure assert "Weather Check" in embed.title - assert len(embed.fields) == 4 # Season, Time, Week, Roll + assert len(embed.fields) == 5 # Season, Time, Week, Roll, Stadium Image assert embed.image.url == mock_team.stadium assert embed.color.value == int(mock_team.color, 16) @pytest.mark.asyncio - async def test_team_resolution_priority(self, commands_cog, mock_interaction, mock_current): + async def test_team_resolution_priority( + self, commands_cog, mock_interaction, mock_current + ): """Test that team resolution follows correct priority order.""" - team1 = TeamFactory.create(id=1, abbrev='NYY', sname='Yankees', lname='New York Yankees', season=12) - team2 = TeamFactory.create(id=2, abbrev='BOS', sname='Red Sox', lname='Boston Red Sox', season=12) - team3 = TeamFactory.create(id=3, abbrev='LAD', sname='Dodgers', lname='Los Angeles Dodgers', season=12) + team1 = TeamFactory.create( + id=1, abbrev="NYY", sname="Yankees", lname="New York Yankees", season=12 + ) + team2 = TeamFactory.create( + id=2, abbrev="BOS", sname="Red Sox", lname="Boston Red Sox", season=12 + ) + team3 = TeamFactory.create( + id=3, abbrev="LAD", sname="Dodgers", lname="Los Angeles Dodgers", season=12 + ) # Test Priority 1: Explicit parameter (should return team1) - with patch('commands.utilities.weather.team_service') as mock_team_service: + with patch("commands.utilities.weather.team_service") as mock_team_service: mock_team_service.get_team_by_abbrev = AsyncMock(return_value=team1) - result = await commands_cog._resolve_team(mock_interaction, 'NYY', 12) - assert result.abbrev == 'NYY' + result = await commands_cog._resolve_team(mock_interaction, "NYY", 12) + assert result.abbrev == "NYY" assert result.id == 1 # Test Priority 2: Channel name (should return team2) mock_interaction.channel.name = "BOS-Fenway-Park" - with patch('commands.utilities.weather.team_service') as mock_team_service: + with patch("commands.utilities.weather.team_service") as mock_team_service: mock_team_service.get_team_by_abbrev = AsyncMock(return_value=team2) result = await commands_cog._resolve_team(mock_interaction, None, 12) - assert result.abbrev == 'BOS' + assert result.abbrev == "BOS" assert result.id == 2 # Test Priority 3: User ownership (should return team3) mock_interaction.channel.name = "general" - with patch('commands.utilities.weather.team_service') as mock_team_service, \ - patch('commands.utilities.weather.get_user_major_league_team') as mock_get_team: + with patch( + "commands.utilities.weather.team_service" + ) as mock_team_service, patch( + "commands.utilities.weather.get_user_major_league_team" + ) as mock_get_team: mock_team_service.get_team_by_abbrev = AsyncMock(return_value=None) mock_get_team.return_value = team3 result = await commands_cog._resolve_team(mock_interaction, None, 12) - assert result.abbrev == 'LAD' + assert result.abbrev == "LAD" assert result.id == 3 @@ -452,12 +548,25 @@ class TestWeatherCommandsIntegration: @pytest.fixture def mock_games(self): """Create mock game schedule for integration tests.""" - yankees = TeamFactory.create(id=499, abbrev='NYY', sname='Yankees', lname='New York Yankees', season=12) - red_sox = TeamFactory.create(id=500, abbrev='BOS', sname='Red Sox', lname='Boston Red Sox', season=12) + yankees = TeamFactory.create( + id=499, abbrev="NYY", sname="Yankees", lname="New York Yankees", season=12 + ) + red_sox = TeamFactory.create( + id=500, abbrev="BOS", sname="Red Sox", lname="Boston Red Sox", season=12 + ) # 1 completed game for division week testing games = [ - GameFactory.completed(id=1, season=12, week=10, game_num=1, away_team=yankees, home_team=red_sox, away_score=5, home_score=3) + GameFactory.completed( + id=1, + season=12, + week=10, + game_num=1, + away_team=yankees, + home_team=red_sox, + away_score=5, + home_score=3, + ) ] return games @@ -470,7 +579,9 @@ class TestWeatherCommandsIntegration: # 1 game played in division week should be Night one_game = [mock_games[0]] time_of_day = commands_cog._get_time_of_day(one_game, week) - assert "Night" in time_of_day, f"Week {week} should be Night with 1 game in division week" + assert ( + "Night" in time_of_day + ), f"Week {week} should be Night with 1 game in division week" @pytest.mark.asyncio async def test_season_transitions(self, commands_cog):