# Shared fixtures and mocks for players refactor tests import pytest import asyncio from unittest.mock import AsyncMock, MagicMock, Mock import discord from discord.ext import commands @pytest.fixture def mock_bot(): """Mock Discord bot for testing.""" bot = AsyncMock(spec=commands.Bot) bot.get_cog = Mock(return_value=None) bot.add_cog = AsyncMock() bot.wait_until_ready = AsyncMock() return bot @pytest.fixture def mock_interaction(): """Mock Discord interaction for slash commands.""" interaction = AsyncMock(spec=discord.Interaction) interaction.response = AsyncMock() interaction.response.defer = AsyncMock() interaction.followup = AsyncMock() interaction.followup.send = AsyncMock() interaction.edit_original_response = AsyncMock() # Mock user interaction.user = Mock(spec=discord.Member) interaction.user.id = 12345 interaction.user.mention = "<@12345>" # Mock channel interaction.channel = Mock(spec=discord.TextChannel) interaction.channel.name = "test-channel" interaction.channel.send = AsyncMock() return interaction @pytest.fixture def mock_context(): """Mock Discord context for traditional commands.""" ctx = AsyncMock(spec=commands.Context) ctx.send = AsyncMock() ctx.author = Mock(spec=discord.Member) ctx.author.id = 12345 ctx.author.mention = "<@12345>" ctx.author.roles = [] ctx.author.guild_permissions = Mock() ctx.author.guild_permissions.administrator = False # Mock channel ctx.channel = Mock(spec=discord.TextChannel) ctx.channel.name = "test-channel" ctx.channel.send = AsyncMock() # Mock guild ctx.guild = Mock(spec=discord.Guild) ctx.guild.roles = [] return ctx @pytest.fixture def sample_player(): """Sample player data for testing.""" return { 'id': 1, 'player_id': 12345, 'name': 'Test Player', 'franchise': 'BOS', 'cardset': 'MLB 2024', 'positions': 'SS, 2B', 'rarity': {'name': 'All-Star', 'value': 3, 'color': '1f8b4c'}, 'cost': 150, 'image': 'https://example.com/player.jpg', 'headshot': 'https://example.com/headshot.jpg', 'batting_card': { 'contact_r': 85, 'contact_l': 80, 'power_r': 70, 'power_l': 65, 'vision': 75, 'speed': 60, 'stealing': 55 }, 'pitching_card': None } @pytest.fixture def sample_team(): """Sample team data for testing.""" return { 'id': 1, 'abbrev': 'TST', 'sname': 'Test', 'lname': 'Test Team', 'gm_id': 12345, 'gmname': 'Test GM', 'gsheet': 'None', 'season': 4, 'wallet': 1000, 'color': 'a6ce39', 'logo': 'https://example.com/logo.png', 'ranking': 85 } @pytest.fixture def sample_cardset(): """Sample cardset data for testing.""" return { 'id': 1, 'name': 'MLB 2024', 'description': 'Major League Baseball 2024 season cards', 'active': True } @pytest.fixture def sample_paperdex(): """Sample paperdex data for testing.""" return { 'id': 1, 'team_id': 1, 'cardset': 'MLB 2024', 'total_cards': 100, 'unique_cards': 45, 'rarity_counts': { 'replacement': 20, 'reserve': 15, 'starter': 8, 'all-star': 2 }, 'team_counts': { 'BOS': 5, 'NYY': 4, 'TB': 3 } } @pytest.fixture def sample_game_data(): """Sample game data for records/standings.""" return [ { 'home_score': 7, 'away_score': 4, 'home_team': {'abbrev': 'BOS', 'is_ai': True}, 'away_team': {'abbrev': 'TST', 'is_ai': False}, 'game_type': 'minor-league', 'created_at': '2024-01-01T12:00:00Z' }, { 'home_score': 3, 'away_score': 8, 'home_team': {'abbrev': 'TST', 'is_ai': False}, 'away_team': {'abbrev': 'NYY', 'is_ai': True}, 'game_type': 'minor-league', 'created_at': '2024-01-02T15:00:00Z' } ] # Mock API calls @pytest.fixture def mock_db_get(monkeypatch): """Mock db_get function for API calls.""" async def mock_get(endpoint, params=None, timeout=None, none_okay=False, object_id=None): if 'players' in endpoint: return { 'count': 1, 'players': [sample_player()] } elif 'teams' in endpoint: return { 'count': 1, 'teams': [sample_team()] } elif 'cardsets' in endpoint: return { 'count': 1, 'cardsets': [sample_cardset()] } elif 'paperdex' in endpoint: return { 'count': 1, 'paperdex': [sample_paperdex()] } else: return {'count': 0} mock_fn = AsyncMock(side_effect=mock_get) monkeypatch.setattr('api_calls.db_get', mock_fn) return mock_fn @pytest.fixture def mock_db_post(monkeypatch): """Mock db_post function for API calls.""" async def mock_post(endpoint, payload=None, timeout=None): return {'id': 1, 'status': 'success', **payload} if payload else {'id': 1, 'status': 'success'} mock_fn = AsyncMock(side_effect=mock_post) monkeypatch.setattr('api_calls.db_post', mock_fn) return mock_fn @pytest.fixture def mock_db_patch(monkeypatch): """Mock db_patch function for API calls.""" async def mock_patch(endpoint, object_id=None, params=None): return {'id': object_id, 'status': 'updated'} mock_fn = AsyncMock(side_effect=mock_patch) monkeypatch.setattr('api_calls.db_patch', mock_fn) return mock_fn @pytest.fixture def mock_db_delete(monkeypatch): """Mock db_delete function for API calls.""" async def mock_delete(endpoint, object_id=None): return {'id': object_id, 'status': 'deleted'} mock_fn = AsyncMock(side_effect=mock_delete) monkeypatch.setattr('api_calls.db_delete', mock_fn) return mock_fn @pytest.fixture def mock_helper_functions(monkeypatch): """Mock helper functions commonly used across modules.""" from unittest.mock import patch # Mock helper functions monkeypatch.setattr('helpers.legal_channel', lambda ctx: True) monkeypatch.setattr('helpers.get_team_by_owner', AsyncMock(return_value=sample_team())) monkeypatch.setattr('helpers.get_card_embeds', lambda player: [Mock(spec=discord.Embed)]) monkeypatch.setattr('helpers.embed_pagination', AsyncMock()) monkeypatch.setattr('helpers.get_team_embed', lambda title, team: Mock(spec=discord.Embed)) monkeypatch.setattr('search_utils.cardset_search', lambda query: ['MLB 2024']) monkeypatch.setattr('search_utils.fuzzy_player_search', lambda query: ['Test Player']) @pytest.fixture def mock_role(): """Mock Discord role for permission testing.""" role = Mock(spec=discord.Role) role.name = "Paper Dynasty Players" return role @pytest.fixture def mock_permissions(): """Mock permission checks.""" def has_role_mock(*role_names): async def decorator(func): return func return decorator return has_role_mock # Event loop fixture for async tests @pytest.fixture(scope="session") def event_loop(): """Create an instance of the default event loop for the test session.""" loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close() @pytest.fixture(autouse=True) def setup_logging(): """Setup logging for tests to avoid noise.""" import logging logging.getLogger('discord_app').setLevel(logging.CRITICAL)