paper-dynasty-discord/tests/players_refactor/conftest.py
2025-08-17 08:46:55 -05:00

283 lines
7.8 KiB
Python

# 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)