Merge pull request 'fix: invoke actual cog callback in test_error_handling_and_logging (#39)' (#54) from ai/paper-dynasty-discord-39 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 46s

Reviewed-on: #54
This commit is contained in:
cal 2026-03-07 07:41:28 +00:00
commit 25bae26f1e

View File

@ -27,498 +27,596 @@ except ImportError:
@pytest.mark.asyncio
class TestTeamManagement:
"""Test suite for TeamManagement cog functionality."""
@pytest.fixture
def team_management_cog(self, mock_bot):
"""Create TeamManagement cog instance for testing."""
return TeamManagement(mock_bot)
async def test_init(self, team_management_cog, mock_bot):
"""Test cog initialization."""
assert team_management_cog.bot == mock_bot
@patch('api_calls.get_team_by_abbrev')
@patch('helpers.get_team_by_owner')
@patch('helpers.team_summary_embed')
async def test_team_command_with_abbreviation_success(self, mock_team_summary,
mock_get_by_owner, mock_get_by_abbrev,
team_management_cog, mock_interaction,
sample_team_data, mock_embed):
@patch("api_calls.get_team_by_abbrev")
@patch("helpers.get_team_by_owner")
@patch("helpers.team_summary_embed")
async def test_team_command_with_abbreviation_success(
self,
mock_team_summary,
mock_get_by_owner,
mock_get_by_abbrev,
team_management_cog,
mock_interaction,
sample_team_data,
mock_embed,
):
"""Test team command with team abbreviation provided."""
mock_get_by_abbrev.return_value = sample_team_data
mock_team_summary.return_value = mock_embed
async def mock_team_command(interaction, team_abbrev=None):
await interaction.response.defer()
if team_abbrev:
team = await mock_get_by_abbrev(team_abbrev)
if not team:
await interaction.followup.send(f'Could not find team with abbreviation: {team_abbrev}')
await interaction.followup.send(
f"Could not find team with abbreviation: {team_abbrev}"
)
return
else:
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet! Use `/newteam` to create one.')
await interaction.followup.send(
"You don't have a team yet! Use `/newteam` to create one."
)
return
embed = await mock_team_summary(team, interaction, include_roster=True)
await interaction.followup.send(embed=embed)
await mock_team_command(mock_interaction, 'TST')
await mock_team_command(mock_interaction, "TST")
mock_interaction.response.defer.assert_called_once()
mock_get_by_abbrev.assert_called_once_with('TST')
mock_get_by_abbrev.assert_called_once_with("TST")
mock_team_summary.assert_called_once()
mock_interaction.followup.send.assert_called_once()
@patch('api_calls.get_team_by_abbrev')
async def test_team_command_abbreviation_not_found(self, mock_get_by_abbrev,
team_management_cog, mock_interaction):
@patch("api_calls.get_team_by_abbrev")
async def test_team_command_abbreviation_not_found(
self, mock_get_by_abbrev, team_management_cog, mock_interaction
):
"""Test team command when abbreviation is not found."""
mock_get_by_abbrev.return_value = None
async def mock_team_command(interaction, team_abbrev):
await interaction.response.defer()
team = await mock_get_by_abbrev(team_abbrev)
if not team:
await interaction.followup.send(f'Could not find team with abbreviation: {team_abbrev}')
await interaction.followup.send(
f"Could not find team with abbreviation: {team_abbrev}"
)
return
await mock_team_command(mock_interaction, 'XYZ')
mock_interaction.followup.send.assert_called_once_with('Could not find team with abbreviation: XYZ')
@patch('helpers.get_team_by_owner')
@patch('helpers.team_summary_embed')
async def test_team_command_without_abbreviation_success(self, mock_team_summary,
mock_get_by_owner,
team_management_cog, mock_interaction,
sample_team_data, mock_embed):
await mock_team_command(mock_interaction, "XYZ")
mock_interaction.followup.send.assert_called_once_with(
"Could not find team with abbreviation: XYZ"
)
@patch("helpers.get_team_by_owner")
@patch("helpers.team_summary_embed")
async def test_team_command_without_abbreviation_success(
self,
mock_team_summary,
mock_get_by_owner,
team_management_cog,
mock_interaction,
sample_team_data,
mock_embed,
):
"""Test team command without abbreviation (user's own team)."""
mock_get_by_owner.return_value = sample_team_data
mock_team_summary.return_value = mock_embed
async def mock_team_command(interaction, team_abbrev=None):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet! Use `/newteam` to create one.')
await interaction.followup.send(
"You don't have a team yet! Use `/newteam` to create one."
)
return
embed = await mock_team_summary(team, interaction, include_roster=True)
await interaction.followup.send(embed=embed)
await mock_team_command(mock_interaction)
mock_get_by_owner.assert_called_once_with(mock_interaction.user.id)
mock_team_summary.assert_called_once()
mock_interaction.followup.send.assert_called_once()
@patch('helpers.get_team_by_owner')
async def test_team_command_user_no_team(self, mock_get_by_owner,
team_management_cog, mock_interaction):
@patch("helpers.get_team_by_owner")
async def test_team_command_user_no_team(
self, mock_get_by_owner, team_management_cog, mock_interaction
):
"""Test team command when user has no team."""
mock_get_by_owner.return_value = None
async def mock_team_command(interaction, team_abbrev=None):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet! Use `/newteam` to create one.')
await interaction.followup.send(
"You don't have a team yet! Use `/newteam` to create one."
)
return
await mock_team_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('You don\'t have a team yet! Use `/newteam` to create one.')
@patch('helpers.get_team_by_owner')
@patch('api_calls.db_patch')
async def test_branding_command_success(self, mock_db_patch, mock_get_by_owner,
team_management_cog, mock_interaction,
sample_team_data):
mock_interaction.followup.send.assert_called_once_with(
"You don't have a team yet! Use `/newteam` to create one."
)
@patch("helpers.get_team_by_owner")
@patch("api_calls.db_patch")
async def test_branding_command_success(
self,
mock_db_patch,
mock_get_by_owner,
team_management_cog,
mock_interaction,
sample_team_data,
):
"""Test successful team branding update."""
mock_get_by_owner.return_value = sample_team_data
mock_db_patch.return_value = {'success': True}
mock_db_patch.return_value = {"success": True}
async def mock_branding_command(interaction, new_color, new_logo_url=None):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
update_data = {'color': new_color}
update_data = {"color": new_color}
if new_logo_url:
update_data['logo'] = new_logo_url
update_data["logo"] = new_logo_url
response = await mock_db_patch(f'teams/{team["id"]}', data=update_data)
if response.get('success'):
await interaction.followup.send(f'Successfully updated team branding!')
if response.get("success"):
await interaction.followup.send(f"Successfully updated team branding!")
else:
await interaction.followup.send('Failed to update team branding.')
await mock_branding_command(mock_interaction, '#FF0000', 'https://example.com/logo.png')
await interaction.followup.send("Failed to update team branding.")
await mock_branding_command(
mock_interaction, "#FF0000", "https://example.com/logo.png"
)
mock_get_by_owner.assert_called_once()
mock_db_patch.assert_called_once()
mock_interaction.followup.send.assert_called_once_with('Successfully updated team branding!')
@patch('helpers.get_team_by_owner')
async def test_branding_command_no_team(self, mock_get_by_owner,
team_management_cog, mock_interaction):
mock_interaction.followup.send.assert_called_once_with(
"Successfully updated team branding!"
)
@patch("helpers.get_team_by_owner")
async def test_branding_command_no_team(
self, mock_get_by_owner, team_management_cog, mock_interaction
):
"""Test team branding command when user has no team."""
mock_get_by_owner.return_value = None
async def mock_branding_command(interaction, new_color):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
await mock_branding_command(mock_interaction, '#FF0000')
mock_interaction.followup.send.assert_called_once_with('You don\'t have a team yet!')
@patch('helpers.get_team_by_owner')
@patch('api_calls.db_patch')
async def test_branding_command_failure(self, mock_db_patch, mock_get_by_owner,
team_management_cog, mock_interaction,
sample_team_data):
await mock_branding_command(mock_interaction, "#FF0000")
mock_interaction.followup.send.assert_called_once_with(
"You don't have a team yet!"
)
@patch("helpers.get_team_by_owner")
@patch("api_calls.db_patch")
async def test_branding_command_failure(
self,
mock_db_patch,
mock_get_by_owner,
team_management_cog,
mock_interaction,
sample_team_data,
):
"""Test team branding update failure."""
mock_get_by_owner.return_value = sample_team_data
mock_db_patch.return_value = {'success': False}
mock_db_patch.return_value = {"success": False}
async def mock_branding_command(interaction, new_color):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
update_data = {'color': new_color}
update_data = {"color": new_color}
response = await mock_db_patch(f'teams/{team["id"]}', data=update_data)
if response.get('success'):
await interaction.followup.send('Successfully updated team branding!')
if response.get("success"):
await interaction.followup.send("Successfully updated team branding!")
else:
await interaction.followup.send('Failed to update team branding.')
await mock_branding_command(mock_interaction, '#FF0000')
mock_interaction.followup.send.assert_called_once_with('Failed to update team branding.')
@patch('helpers.get_team_by_owner')
@patch('pygsheets.authorize')
@patch('helpers.get_roster_sheet')
async def test_pullroster_command_success(self, mock_get_roster_sheet, mock_authorize,
mock_get_by_owner, team_management_cog,
mock_interaction, sample_team_data):
await interaction.followup.send("Failed to update team branding.")
await mock_branding_command(mock_interaction, "#FF0000")
mock_interaction.followup.send.assert_called_once_with(
"Failed to update team branding."
)
@patch("helpers.get_team_by_owner")
@patch("pygsheets.authorize")
@patch("helpers.get_roster_sheet")
async def test_pullroster_command_success(
self,
mock_get_roster_sheet,
mock_authorize,
mock_get_by_owner,
team_management_cog,
mock_interaction,
sample_team_data,
):
"""Test successful roster pull from Google Sheets."""
mock_get_by_owner.return_value = sample_team_data
mock_gc = Mock()
mock_authorize.return_value = mock_gc
mock_get_roster_sheet.return_value = Mock()
async def mock_pullroster_command(interaction):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
if not team.get('gsheet'):
await interaction.followup.send('No Google Sheet configured for your team.')
if not team.get("gsheet"):
await interaction.followup.send(
"No Google Sheet configured for your team."
)
return
try:
gc = mock_authorize()
roster_data = await mock_get_roster_sheet(gc, team['gsheet'])
await interaction.followup.send('Successfully pulled roster from Google Sheets!')
roster_data = await mock_get_roster_sheet(gc, team["gsheet"])
await interaction.followup.send(
"Successfully pulled roster from Google Sheets!"
)
except Exception as e:
await interaction.followup.send(f'Error pulling roster: {str(e)}')
await interaction.followup.send(f"Error pulling roster: {str(e)}")
await mock_pullroster_command(mock_interaction)
mock_get_by_owner.assert_called_once()
mock_authorize.assert_called_once()
mock_get_roster_sheet.assert_called_once()
mock_interaction.followup.send.assert_called_once_with('Successfully pulled roster from Google Sheets!')
@patch('helpers.get_team_by_owner')
async def test_pullroster_command_no_team(self, mock_get_by_owner,
team_management_cog, mock_interaction):
mock_interaction.followup.send.assert_called_once_with(
"Successfully pulled roster from Google Sheets!"
)
@patch("helpers.get_team_by_owner")
async def test_pullroster_command_no_team(
self, mock_get_by_owner, team_management_cog, mock_interaction
):
"""Test roster pull when user has no team."""
mock_get_by_owner.return_value = None
async def mock_pullroster_command(interaction):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
await mock_pullroster_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('You don\'t have a team yet!')
@patch('helpers.get_team_by_owner')
async def test_pullroster_command_no_sheet(self, mock_get_by_owner,
team_management_cog, mock_interaction):
mock_interaction.followup.send.assert_called_once_with(
"You don't have a team yet!"
)
@patch("helpers.get_team_by_owner")
async def test_pullroster_command_no_sheet(
self, mock_get_by_owner, team_management_cog, mock_interaction
):
"""Test roster pull when team has no Google Sheet configured."""
team_data_no_sheet = {**sample_team_data, 'gsheet': None}
team_data_no_sheet = {**sample_team_data, "gsheet": None}
mock_get_by_owner.return_value = team_data_no_sheet
async def mock_pullroster_command(interaction):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
if not team.get('gsheet'):
await interaction.followup.send('No Google Sheet configured for your team.')
if not team.get("gsheet"):
await interaction.followup.send(
"No Google Sheet configured for your team."
)
return
await mock_pullroster_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('No Google Sheet configured for your team.')
@patch('helpers.get_team_by_owner')
@patch('pygsheets.authorize')
async def test_pullroster_command_error(self, mock_authorize, mock_get_by_owner,
team_management_cog, mock_interaction,
sample_team_data):
mock_interaction.followup.send.assert_called_once_with(
"No Google Sheet configured for your team."
)
@patch("helpers.get_team_by_owner")
@patch("pygsheets.authorize")
async def test_pullroster_command_error(
self,
mock_authorize,
mock_get_by_owner,
team_management_cog,
mock_interaction,
sample_team_data,
):
"""Test roster pull error handling."""
mock_get_by_owner.return_value = sample_team_data
mock_authorize.side_effect = Exception("Google Sheets API Error")
async def mock_pullroster_command(interaction):
await interaction.response.defer()
team = await mock_get_by_owner(interaction.user.id)
if not team:
await interaction.followup.send('You don\'t have a team yet!')
await interaction.followup.send("You don't have a team yet!")
return
if not team.get('gsheet'):
await interaction.followup.send('No Google Sheet configured for your team.')
if not team.get("gsheet"):
await interaction.followup.send(
"No Google Sheet configured for your team."
)
return
try:
gc = mock_authorize()
except Exception as e:
await interaction.followup.send(f'Error pulling roster: {str(e)}')
await interaction.followup.send(f"Error pulling roster: {str(e)}")
await mock_pullroster_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('Error pulling roster: Google Sheets API Error')
@patch('api_calls.db_get')
async def test_ai_teams_command_success(self, mock_db_get, team_management_cog,
mock_interaction, mock_embed):
mock_interaction.followup.send.assert_called_once_with(
"Error pulling roster: Google Sheets API Error"
)
@patch("api_calls.db_get")
async def test_ai_teams_command_success(
self, mock_db_get, team_management_cog, mock_interaction, mock_embed
):
"""Test successful AI teams listing."""
ai_teams_data = {
'count': 2,
'teams': [
{'id': 1, 'abbrev': 'AI1', 'sname': 'AI Team 1', 'is_ai': True},
{'id': 2, 'abbrev': 'AI2', 'sname': 'AI Team 2', 'is_ai': True}
]
"count": 2,
"teams": [
{"id": 1, "abbrev": "AI1", "sname": "AI Team 1", "is_ai": True},
{"id": 2, "abbrev": "AI2", "sname": "AI Team 2", "is_ai": True},
],
}
mock_db_get.return_value = ai_teams_data
async def mock_ai_teams_command(interaction):
await interaction.response.defer()
teams_response = await mock_db_get('teams', params=[('is_ai', 'true')])
if not teams_response or teams_response['count'] == 0:
await interaction.followup.send('No AI teams found.')
teams_response = await mock_db_get("teams", params=[("is_ai", "true")])
if not teams_response or teams_response["count"] == 0:
await interaction.followup.send("No AI teams found.")
return
ai_teams = teams_response['teams']
team_list = '\n'.join([f"{team['abbrev']} - {team['sname']}" for team in ai_teams])
ai_teams = teams_response["teams"]
team_list = "\n".join(
[f"{team['abbrev']} - {team['sname']}" for team in ai_teams]
)
embed = mock_embed
embed.title = f'AI Teams ({len(ai_teams)})'
embed.title = f"AI Teams ({len(ai_teams)})"
embed.description = team_list
await interaction.followup.send(embed=embed)
await mock_ai_teams_command(mock_interaction)
mock_db_get.assert_called_once_with('teams', params=[('is_ai', 'true')])
mock_db_get.assert_called_once_with("teams", params=[("is_ai", "true")])
mock_interaction.followup.send.assert_called_once()
@patch('api_calls.db_get')
async def test_ai_teams_command_no_teams(self, mock_db_get, team_management_cog,
mock_interaction):
@patch("api_calls.db_get")
async def test_ai_teams_command_no_teams(
self, mock_db_get, team_management_cog, mock_interaction
):
"""Test AI teams command when no AI teams exist."""
mock_db_get.return_value = {'count': 0, 'teams': []}
mock_db_get.return_value = {"count": 0, "teams": []}
async def mock_ai_teams_command(interaction):
await interaction.response.defer()
teams_response = await mock_db_get('teams', params=[('is_ai', 'true')])
if not teams_response or teams_response['count'] == 0:
await interaction.followup.send('No AI teams found.')
teams_response = await mock_db_get("teams", params=[("is_ai", "true")])
if not teams_response or teams_response["count"] == 0:
await interaction.followup.send("No AI teams found.")
return
await mock_ai_teams_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('No AI teams found.')
@patch('api_calls.db_get')
async def test_ai_teams_command_api_error(self, mock_db_get, team_management_cog,
mock_interaction):
mock_interaction.followup.send.assert_called_once_with("No AI teams found.")
@patch("api_calls.db_get")
async def test_ai_teams_command_api_error(
self, mock_db_get, team_management_cog, mock_interaction
):
"""Test AI teams command API error handling."""
mock_db_get.return_value = None
async def mock_ai_teams_command(interaction):
await interaction.response.defer()
teams_response = await mock_db_get('teams', params=[('is_ai', 'true')])
teams_response = await mock_db_get("teams", params=[("is_ai", "true")])
if not teams_response:
await interaction.followup.send('Error retrieving AI teams.')
await interaction.followup.send("Error retrieving AI teams.")
return
await mock_ai_teams_command(mock_interaction)
mock_interaction.followup.send.assert_called_once_with('Error retrieving AI teams.')
mock_interaction.followup.send.assert_called_once_with(
"Error retrieving AI teams."
)
def test_color_validation(self, team_management_cog):
"""Test color format validation for branding command."""
valid_colors = ['#FF0000', '#00FF00', '#0000FF', 'FF0000', '123ABC']
invalid_colors = ['invalid', '#GGGGGG', '12345', '#1234567']
valid_colors = ["#FF0000", "#00FF00", "#0000FF", "FF0000", "123ABC"]
invalid_colors = ["invalid", "#GGGGGG", "12345", "#1234567"]
def is_valid_color(color):
# Basic hex color validation
if color.startswith('#'):
if color.startswith("#"):
color = color[1:]
return len(color) == 6 and all(c in '0123456789ABCDEFabcdef' for c in color)
return len(color) == 6 and all(c in "0123456789ABCDEFabcdef" for c in color)
for color in valid_colors:
assert is_valid_color(color), f"Color {color} should be valid"
for color in invalid_colors:
assert not is_valid_color(color), f"Color {color} should be invalid"
def test_url_validation(self, team_management_cog):
"""Test URL validation for logo updates."""
valid_urls = [
'https://example.com/image.png',
'https://cdn.example.com/logo.jpg',
'http://test.com/image.gif'
"https://example.com/image.png",
"https://cdn.example.com/logo.jpg",
"http://test.com/image.gif",
]
invalid_urls = [
'not_a_url',
'ftp://example.com/file.txt',
'javascript:alert(1)'
"not_a_url",
"ftp://example.com/file.txt",
"javascript:alert(1)",
]
def is_valid_url(url):
return url.startswith(('http://', 'https://'))
return url.startswith(("http://", "https://"))
for url in valid_urls:
assert is_valid_url(url), f"URL {url} should be valid"
for url in invalid_urls:
assert not is_valid_url(url), f"URL {url} should be invalid"
@patch('helpers.get_rosters')
async def test_roster_integration(self, mock_get_rosters, team_management_cog,
sample_team_data):
@patch("helpers.get_rosters")
async def test_roster_integration(
self, mock_get_rosters, team_management_cog, sample_team_data
):
"""Test roster data integration with team display."""
roster_data = {
'active_roster': [
{'card_id': 1, 'player_name': 'Player 1', 'position': 'C'},
{'card_id': 2, 'player_name': 'Player 2', 'position': '1B'}
"active_roster": [
{"card_id": 1, "player_name": "Player 1", "position": "C"},
{"card_id": 2, "player_name": "Player 2", "position": "1B"},
],
'bench': [
{'card_id': 3, 'player_name': 'Player 3', 'position': 'OF'}
]
"bench": [{"card_id": 3, "player_name": "Player 3", "position": "OF"}],
}
mock_get_rosters.return_value = roster_data
rosters = await mock_get_rosters(sample_team_data['id'])
rosters = await mock_get_rosters(sample_team_data["id"])
assert rosters is not None
assert 'active_roster' in rosters
assert 'bench' in rosters
assert len(rosters['active_roster']) == 2
assert len(rosters['bench']) == 1
def test_team_embed_formatting(self, team_management_cog, sample_team_data, mock_embed):
assert "active_roster" in rosters
assert "bench" in rosters
assert len(rosters["active_roster"]) == 2
assert len(rosters["bench"]) == 1
def test_team_embed_formatting(
self, team_management_cog, sample_team_data, mock_embed
):
"""Test proper formatting of team summary embeds."""
# Mock the team summary embed creation
def create_team_summary_embed(team, include_roster=False):
embed = mock_embed
embed.title = f"{team['abbrev']} - {team['sname']}"
embed.add_field(name="GM", value=team['gmname'], inline=True)
embed.add_field(name="GM", value=team["gmname"], inline=True)
embed.add_field(name="Wallet", value=f"${team['wallet']}", inline=True)
embed.add_field(name="Team Value", value=f"${team['team_value']}", inline=True)
if team['color']:
embed.color = int(team['color'], 16)
embed.add_field(
name="Team Value", value=f"${team['team_value']}", inline=True
)
if team["color"]:
embed.color = int(team["color"], 16)
if include_roster:
embed.add_field(name="Roster", value="Active roster info...", inline=False)
embed.add_field(
name="Roster", value="Active roster info...", inline=False
)
return embed
embed = create_team_summary_embed(sample_team_data, include_roster=True)
assert embed.title == f"{sample_team_data['abbrev']} - {sample_team_data['sname']}"
assert (
embed.title == f"{sample_team_data['abbrev']} - {sample_team_data['sname']}"
)
embed.add_field.assert_called()
def test_permission_checks(self, team_management_cog, mock_interaction):
"""Test role and channel permission checking."""
# Test role check
mock_member_with_role = Mock()
mock_member_with_role.roles = [Mock(name='Paper Dynasty')]
mock_member_with_role.roles = [Mock(name="Paper Dynasty")]
mock_interaction.user = mock_member_with_role
# Test channel check
with patch('helpers.legal_channel') as mock_legal_check:
with patch("helpers.legal_channel") as mock_legal_check:
mock_legal_check.return_value = True
result = mock_legal_check(mock_interaction.channel)
assert result is True
@patch('logging.getLogger')
async def test_error_handling_and_logging(self, mock_logger, team_management_cog):
"""Test error handling and logging across team management operations."""
mock_logger_instance = Mock()
mock_logger.return_value = mock_logger_instance
# Test API timeout error
with patch('api_calls.db_get') as mock_db_get:
mock_db_get.side_effect = asyncio.TimeoutError("Request timeout")
try:
await mock_db_get('teams')
except asyncio.TimeoutError:
# In actual implementation, this would be caught and logged
pass
# Test Google Sheets authentication error
with patch('pygsheets.authorize') as mock_authorize:
mock_authorize.side_effect = Exception("Auth failed")
try:
mock_authorize()
except Exception:
# In actual implementation, this would be caught and logged
pass
async def test_error_handling_and_logging(self, team_management_cog, mock_context):
"""Test that pull_roster_command sends an error message when get_rosters raises.
Invokes the actual cog method callback so the test fails if the method body is
removed or the exception-handling branch is broken.
"""
cmd = getattr(team_management_cog, "pull_roster_command", None)
if cmd is None or not hasattr(cmd, "callback"):
pytest.skip(
"TeamManagement cog not importable; cannot test callback directly"
)
team_with_sheet = {
"id": 1,
"abbrev": "TST",
"sname": "Test",
"gsheet": "valid-sheet-id",
}
with patch(
"cogs.players_new.team_management.get_context_user"
) as mock_get_ctx_user, patch(
"cogs.players_new.team_management.get_team_by_owner",
new=AsyncMock(return_value=team_with_sheet),
), patch(
"cogs.players_new.team_management.get_rosters",
side_effect=Exception("Connection error"),
):
mock_get_ctx_user.return_value = mock_context.author
await cmd.callback(team_management_cog, mock_context)
mock_context.send.assert_called_once_with(
"Could not retrieve rosters from your sheet."
)