strat-gameplay-webapp/backend/tests/unit/config/test_league_configs.py
Cal Corum 197d91edfb CLAUDE: Remove defensive alignment field completely
Removed the unused alignment field from DefensiveDecision model and all
related code across backend and frontend.

Backend changes:
- models/game_models.py: Removed alignment field and validator
- terminal_client/display.py: Removed alignment from display
- core/ai_opponent.py: Updated log message
- tests/unit/models/test_game_models.py: Removed alignment tests
- tests/unit/core/test_validators.py: Removed alignment validation test

Frontend changes:
- types/game.ts: Removed alignment from DefensiveDecision interface
- components/Decisions/DefensiveSetup.vue:
  * Removed alignment section from template
  * Removed alignment from localSetup initialization
  * Removed alignmentOptions array
  * Removed alignmentDisplay computed property
  * Removed alignment from hasChanges comparison
  * Removed alignment from visual preview (reorganized to col-span-2)

Rationale: Defensive alignment is not active in the game and will not be
used. Per Cal's decision, remove completely rather than keep as dead code.

Tests: All 728 backend unit tests passing (100%)

Session 1 Part 3 - Change #6 complete
Part of cleanup work from demo review

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:02:22 -06:00

207 lines
6.7 KiB
Python

"""
Unit tests for league configuration system.
Tests:
- Config loading and registry
- Config immutability
- Abstract method implementations
- League-specific settings
"""
import pytest
from pydantic import ValidationError
from app.config import (
BaseGameConfig,
SbaConfig,
PdConfig,
LEAGUE_CONFIGS,
get_league_config
)
class TestBaseGameConfig:
"""Tests for BaseGameConfig abstract class."""
def test_cannot_instantiate_abstract_base(self):
"""BaseGameConfig cannot be instantiated directly."""
with pytest.raises(TypeError):
BaseGameConfig(league_id="test")
class TestSbaConfig:
"""Tests for SBA league configuration."""
def test_sba_config_creation(self):
"""Can create SBA config instance."""
config = SbaConfig()
assert config.league_id == "sba"
assert config.version == "1.0.0"
def test_sba_basic_rules(self):
"""SBA uses standard baseball rules."""
config = SbaConfig()
assert config.innings == 9
assert config.outs_per_inning == 3
def test_sba_result_chart_name(self):
"""SBA uses sba_standard_v1 chart."""
config = SbaConfig()
assert config.get_result_chart_name() == "sba_standard_v1"
def test_sba_supports_auto_mode(self):
"""SBA does not support auto mode (cards not digitized)."""
config = SbaConfig()
assert config.supports_auto_mode() is False
def test_sba_api_url(self):
"""SBA API URL is correct."""
config = SbaConfig()
assert config.get_api_base_url() == "https://api.sba.manticorum.com"
def test_sba_player_selection_mode(self):
"""SBA uses manual player selection."""
config = SbaConfig()
assert config.player_selection_mode == "manual"
def test_sba_config_is_immutable(self):
"""Config cannot be modified after creation."""
config = SbaConfig()
with pytest.raises(ValidationError):
config.innings = 7
class TestPdConfig:
"""Tests for PD league configuration."""
def test_pd_config_creation(self):
"""Can create PD config instance."""
config = PdConfig()
assert config.league_id == "pd"
assert config.version == "1.0.0"
def test_pd_basic_rules(self):
"""PD uses standard baseball rules."""
config = PdConfig()
assert config.innings == 9
assert config.outs_per_inning == 3
def test_pd_result_chart_name(self):
"""PD uses pd_standard_v1 chart."""
config = PdConfig()
assert config.get_result_chart_name() == "pd_standard_v1"
def test_pd_supports_auto_mode(self):
"""PD supports auto mode (digitized card data)."""
config = PdConfig()
assert config.supports_auto_mode() is True
def test_pd_api_url(self):
"""PD API URL is correct."""
config = PdConfig()
assert config.get_api_base_url() == "https://pd.manticorum.com/api/"
def test_pd_player_selection_mode(self):
"""PD uses flexible player selection."""
config = PdConfig()
assert config.player_selection_mode == "flexible"
def test_pd_scouting_model_enabled(self):
"""PD has scouting model enabled."""
config = PdConfig()
assert config.use_scouting_model is True
def test_pd_cardset_validation_enabled(self):
"""PD has cardset validation enabled."""
config = PdConfig()
assert config.cardset_validation is True
def test_pd_advanced_analytics_enabled(self):
"""PD has advanced analytics enabled."""
config = PdConfig()
assert config.detailed_analytics is True
assert config.wpa_calculation is True
def test_pd_config_is_immutable(self):
"""Config cannot be modified after creation."""
config = PdConfig()
with pytest.raises(ValidationError):
config.use_scouting_model = False
class TestLeagueRegistry:
"""Tests for league config registry and getter."""
def test_registry_contains_both_leagues(self):
"""Registry has both SBA and PD configs."""
assert "sba" in LEAGUE_CONFIGS
assert "pd" in LEAGUE_CONFIGS
assert len(LEAGUE_CONFIGS) == 2
def test_registry_configs_are_correct_type(self):
"""Registry contains correct config types."""
assert isinstance(LEAGUE_CONFIGS["sba"], SbaConfig)
assert isinstance(LEAGUE_CONFIGS["pd"], PdConfig)
def test_get_sba_config(self):
"""Can get SBA config via getter."""
config = get_league_config("sba")
assert isinstance(config, SbaConfig)
assert config.league_id == "sba"
def test_get_pd_config(self):
"""Can get PD config via getter."""
config = get_league_config("pd")
assert isinstance(config, PdConfig)
assert config.league_id == "pd"
def test_get_invalid_league_raises(self):
"""Getting invalid league raises ValueError."""
with pytest.raises(ValueError) as exc_info:
get_league_config("invalid")
assert "Unknown league: invalid" in str(exc_info.value)
assert "sba" in str(exc_info.value)
assert "pd" in str(exc_info.value)
def test_registry_returns_same_instance(self):
"""Registry returns singleton instances."""
config1 = get_league_config("sba")
config2 = get_league_config("sba")
assert config1 is config2
class TestConfigDifferences:
"""Tests for differences between league configs."""
def test_different_result_charts(self):
"""SBA and PD use different result charts."""
sba = get_league_config("sba")
pd = get_league_config("pd")
assert sba.get_result_chart_name() != pd.get_result_chart_name()
def test_different_api_urls(self):
"""SBA and PD have different API URLs."""
sba = get_league_config("sba")
pd = get_league_config("pd")
assert sba.get_api_base_url() != pd.get_api_base_url()
def test_different_player_selection_modes(self):
"""SBA and PD have different selection modes."""
sba = get_league_config("sba")
pd = get_league_config("pd")
assert sba.player_selection_mode == "manual"
assert pd.player_selection_mode == "flexible"
def test_pd_has_extra_features(self):
"""PD has features that SBA doesn't."""
pd = get_league_config("pd")
sba = get_league_config("sba")
# PD-specific attributes
assert hasattr(pd, 'use_scouting_model')
assert hasattr(pd, 'cardset_validation')
assert hasattr(pd, 'detailed_analytics')
# SBA doesn't have these (or they're False/None)
assert not hasattr(sba, 'use_scouting_model')
assert not hasattr(sba, 'cardset_validation')