major-domo-v2/tests/test_models_transaction.py
Cal Corum f64fee8d2e fix: remove 226 unused imports across the codebase (closes #33)
Ran `ruff check --select F401 --fix` to auto-remove 221 unused imports,
manually removed 4 unused `import discord` from package __init__.py files,
and fixed test import for DISAPPOINTMENT_TIERS to reference canonical location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:35:04 -06:00

340 lines
13 KiB
Python

"""
Tests for Transaction model
Validates transaction model creation, validation, and business logic.
"""
import pytest
import copy
from models.transaction import Transaction, RosterValidation
class TestTransaction:
"""Test Transaction model functionality."""
def test_transaction_creation_from_minimal_api_data(self):
"""Test creating transaction from minimal API data."""
# Create minimal test data matching actual API structure
player_data = {
'id': 12472,
'name': 'Test Player',
'wara': 2.47,
'season': 12,
'pos_1': 'LF'
}
team_data = {
'id': 508,
'abbrev': 'NYD',
'sname': 'Diamonds',
'lname': 'New York Diamonds',
'season': 12
}
transaction_data = {
'id': 27787,
'week': 10,
'season': 12,
'moveid': 'Season-012-Week-10-19-13:04:41',
'player': player_data,
'oldteam': team_data.copy(),
'newteam': {**team_data, 'id': 499, 'abbrev': 'WV', 'sname': 'Black Bears', 'lname': 'West Virginia Black Bears'},
'cancelled': False,
'frozen': False
}
transaction = Transaction.from_api_data(transaction_data)
assert transaction.id == 27787
assert transaction.week == 10
assert transaction.season == 12
assert transaction.moveid == 'Season-012-Week-10-19-13:04:41'
assert transaction.player.name == 'Test Player'
assert transaction.oldteam.abbrev == 'NYD'
assert transaction.newteam.abbrev == 'WV'
assert transaction.cancelled is False
assert transaction.frozen is False
def test_transaction_creation_from_complete_api_data(self):
"""Test creating transaction from complete API data structure."""
complete_data = {
'id': 27787,
'week': 10,
'player': {
'id': 12472,
'name': 'Yordan Alvarez',
'wara': 2.47,
'image': 'https://example.com/image.png',
'image2': None,
'team': {
'id': 508,
'abbrev': 'NYD',
'sname': 'Diamonds',
'lname': 'New York Diamonds',
'season': 12
},
'season': 12,
'pitcher_injury': None,
'pos_1': 'LF',
'pos_2': None,
'last_game': None,
'il_return': None,
'demotion_week': 1,
'headshot': None,
'strat_code': 'Alvarez,Y',
'bbref_id': 'alvaryo01',
'injury_rating': '1p65'
},
'oldteam': {
'id': 508,
'abbrev': 'NYD',
'sname': 'Diamonds',
'lname': 'New York Diamonds',
'season': 12
},
'newteam': {
'id': 499,
'abbrev': 'WV',
'sname': 'Black Bears',
'lname': 'West Virginia Black Bears',
'season': 12
},
'season': 12,
'moveid': 'Season-012-Week-10-19-13:04:41',
'cancelled': False,
'frozen': False
}
transaction = Transaction.from_api_data(complete_data)
assert transaction.id == 27787
assert transaction.player.name == 'Yordan Alvarez'
assert transaction.player.wara == 2.47
assert transaction.player.bbref_id == 'alvaryo01'
assert transaction.oldteam.lname == 'New York Diamonds'
assert transaction.newteam.lname == 'West Virginia Black Bears'
def test_transaction_status_properties(self):
"""Test transaction status property logic."""
base_data = self._create_base_transaction_data()
# Test pending transaction (not frozen, not cancelled)
pending_data = {**base_data, 'cancelled': False, 'frozen': False}
pending_transaction = Transaction.from_api_data(pending_data)
assert pending_transaction.is_pending is True
assert pending_transaction.is_frozen is False
assert pending_transaction.is_cancelled is False
assert pending_transaction.status_text == 'Pending'
assert pending_transaction.status_emoji == ''
# Test frozen transaction
frozen_data = {**base_data, 'cancelled': False, 'frozen': True}
frozen_transaction = Transaction.from_api_data(frozen_data)
assert frozen_transaction.is_pending is False
assert frozen_transaction.is_frozen is True
assert frozen_transaction.is_cancelled is False
assert frozen_transaction.status_text == 'Frozen'
assert frozen_transaction.status_emoji == '❄️'
# Test cancelled transaction
cancelled_data = {**base_data, 'cancelled': True, 'frozen': False}
cancelled_transaction = Transaction.from_api_data(cancelled_data)
assert cancelled_transaction.is_pending is False
assert cancelled_transaction.is_frozen is False
assert cancelled_transaction.is_cancelled is True
assert cancelled_transaction.status_text == 'Cancelled'
assert cancelled_transaction.status_emoji == ''
def test_transaction_move_description(self):
"""Test move description generation."""
transaction_data = self._create_base_transaction_data()
transaction = Transaction.from_api_data(transaction_data)
expected_description = 'Test Player: NYD → WV'
assert transaction.move_description == expected_description
def test_transaction_string_representation(self):
"""Test transaction string representation."""
transaction_data = self._create_base_transaction_data()
transaction = Transaction.from_api_data(transaction_data)
expected_str = '📋 Week 10: Test Player: NYD → WV - ⏳ Pending'
assert str(transaction) == expected_str
def test_major_league_move_detection(self):
"""Test major league move detection logic."""
base_data = self._create_base_transaction_data()
# Test major league to major league (should be True)
ml_to_ml_data = copy.deepcopy(base_data)
ml_to_ml = Transaction.from_api_data(ml_to_ml_data)
assert ml_to_ml.is_major_league_move is True
# Test major league to minor league (should be True)
ml_to_minor_data = copy.deepcopy(base_data)
ml_to_minor_data['newteam']['abbrev'] = 'WVMiL'
ml_to_minor = Transaction.from_api_data(ml_to_minor_data)
assert ml_to_minor.is_major_league_move is True
# Test minor league to major league (should be True)
minor_to_ml_data = copy.deepcopy(base_data)
minor_to_ml_data['oldteam']['abbrev'] = 'NYDMiL'
minor_to_ml = Transaction.from_api_data(minor_to_ml_data)
assert minor_to_ml.is_major_league_move is True
# Test FA to major league (should be True)
fa_to_ml_data = copy.deepcopy(base_data)
fa_to_ml_data['oldteam']['abbrev'] = 'FA'
fa_to_ml = Transaction.from_api_data(fa_to_ml_data)
assert fa_to_ml.is_major_league_move is True
# Test major league to FA (should be True)
ml_to_fa_data = copy.deepcopy(base_data)
ml_to_fa_data['newteam']['abbrev'] = 'FA'
ml_to_fa = Transaction.from_api_data(ml_to_fa_data)
assert ml_to_fa.is_major_league_move is True
# Test minor league to minor league (should be False)
minor_to_minor_data = copy.deepcopy(base_data)
minor_to_minor_data['oldteam']['abbrev'] = 'NYDMiL'
minor_to_minor_data['newteam']['abbrev'] = 'WVMiL'
minor_to_minor = Transaction.from_api_data(minor_to_minor_data)
assert minor_to_minor.is_major_league_move is False
# Test FA to FA (should be False - shouldn't happen but test edge case)
fa_to_fa_data = copy.deepcopy(base_data)
fa_to_fa_data['oldteam']['abbrev'] = 'FA'
fa_to_fa_data['newteam']['abbrev'] = 'FA'
fa_to_fa = Transaction.from_api_data(fa_to_fa_data)
assert fa_to_fa.is_major_league_move is False
def test_transaction_validation_errors(self):
"""Test transaction model validation with invalid data."""
# Test missing required fields
with pytest.raises(Exception): # Pydantic validation error
Transaction.from_api_data({})
with pytest.raises(Exception): # Missing player
Transaction.from_api_data({
'id': 1,
'week': 10,
'season': 12,
'moveid': 'test'
})
def _create_base_transaction_data(self):
"""Create base transaction data for testing."""
return {
'id': 27787,
'week': 10,
'season': 12,
'moveid': 'Season-012-Week-10-19-13:04:41',
'player': {
'id': 12472,
'name': 'Test Player',
'wara': 2.47,
'season': 12,
'pos_1': 'LF'
},
'oldteam': {
'id': 508,
'abbrev': 'NYD',
'sname': 'Diamonds',
'lname': 'New York Diamonds',
'season': 12
},
'newteam': {
'id': 499,
'abbrev': 'WV',
'sname': 'Black Bears',
'lname': 'West Virginia Black Bears',
'season': 12
},
'cancelled': False,
'frozen': False
}
class TestRosterValidation:
"""Test RosterValidation model functionality."""
def test_roster_validation_creation(self):
"""Test creating roster validation instance."""
validation = RosterValidation(
is_legal=True,
total_players=25,
active_players=25,
il_players=0,
total_sWAR=125.5
)
assert validation.is_legal is True
assert validation.total_players == 25
assert validation.active_players == 25
assert validation.il_players == 0
assert validation.total_sWAR == 125.5
assert validation.has_issues is False
def test_roster_validation_with_errors(self):
"""Test roster validation with errors."""
validation = RosterValidation(
is_legal=False,
errors=['Too many players on roster', 'Invalid player position'],
warnings=['Low WARA total'],
total_players=30,
active_players=28,
il_players=2,
total_sWAR=95.2
)
assert validation.is_legal is False
assert len(validation.errors) == 2
assert len(validation.warnings) == 1
assert validation.has_issues is True
assert validation.status_emoji == ''
def test_roster_validation_with_warnings_only(self):
"""Test roster validation with warnings but no errors."""
validation = RosterValidation(
is_legal=True,
warnings=['Roster could use more depth'],
total_players=23,
active_players=23,
total_sWAR=110.0
)
assert validation.is_legal is True
assert len(validation.errors) == 0
assert len(validation.warnings) == 1
assert validation.has_issues is True
assert validation.status_emoji == '⚠️'
def test_roster_validation_perfect(self):
"""Test perfectly valid roster."""
validation = RosterValidation(
is_legal=True,
total_players=25,
active_players=25,
total_sWAR=130.0
)
assert validation.is_legal is True
assert len(validation.errors) == 0
assert len(validation.warnings) == 0
assert validation.has_issues is False
assert validation.status_emoji == ''
def test_roster_validation_defaults(self):
"""Test roster validation with default values."""
validation = RosterValidation(is_legal=True)
assert validation.total_players == 0
assert validation.active_players == 0
assert validation.il_players == 0
assert validation.minor_league_players == 0
assert validation.total_sWAR == 0.0
assert len(validation.errors) == 0
assert len(validation.warnings) == 0