CLAUDE: Update tests to match Phase 2 model changes

- Update test fixtures to provide required current_batter_lineup_id field
- Update validator tests for new infield depth values (infield_in, normal, corners_in)
- Update runner advancement tests to match refactored runner management
- Update game model tests to work with direct base references
- Update play resolver tests for enhanced logic
- Add missing imports in test files

All changes ensure tests align with recent Phase 2 implementation updates
including the transition from RunnerState list to direct base references
(on_first, on_second, on_third) in GameState model.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2025-10-31 16:11:39 -05:00
parent 76e24ab22b
commit 23a0a1db4e
7 changed files with 158 additions and 73 deletions

View File

@ -70,7 +70,8 @@ class TestResolveOutcome:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
ab_roll = create_mock_ab_roll(state.game_id)
@ -99,7 +100,8 @@ class TestResolveOutcome:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
ab_roll = create_mock_ab_roll(state.game_id)
@ -127,6 +129,7 @@ class TestResolveOutcome:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="RF", batting_order=2),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="SS", batting_order=3)
@ -152,7 +155,8 @@ class TestResolveOutcome:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
ab_roll = create_mock_ab_roll(state.game_id)
@ -180,6 +184,7 @@ class TestResolveOutcome:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="RF", batting_order=2),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="SS", batting_order=3)

View File

@ -17,10 +17,21 @@ from app.core.runner_advancement import (
RunnerMovement,
AdvancementResult
)
from app.models.game_models import GameState, DefensiveDecision
from app.models.game_models import GameState, DefensiveDecision, LineupPlayerState
from app.config.result_charts import PlayOutcome
# Helper function to create mock runners
def create_runner(lineup_id: int) -> LineupPlayerState:
"""Create a LineupPlayerState for testing."""
return LineupPlayerState(
lineup_id=lineup_id,
card_id=lineup_id * 100, # Arbitrary card_id
position="CF",
batting_order=lineup_id
)
# ========================================
# Fixtures
# ========================================
@ -107,9 +118,9 @@ class TestChartLookup:
"""With 2 outs, always batter out regardless of situation."""
base_state.current_on_base_code = 7 # Bases loaded
base_state.outs = 2
base_state.on_first = 2
base_state.on_second = 3
base_state.on_third = 4
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.on_third = create_runner(4)
result = advancement.advance_runners(
outcome=PlayOutcome.GROUNDBALL_A,
@ -125,7 +136,7 @@ class TestChartLookup:
"""Runner on 1st, GBA, Infield Back → Result 2 (DP attempt)."""
base_state.current_on_base_code = 1
base_state.outs = 0
base_state.on_first = 2
base_state.on_first = create_runner(2)
base_state.is_runner_on_first = Mock(return_value=True)
result = advancement.advance_runners(
@ -141,7 +152,7 @@ class TestChartLookup:
"""Runner on 3rd, GBA, Infield In → Result 7 (forced advancement)."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -157,9 +168,9 @@ class TestChartLookup:
"""Bases loaded, GBA, Infield In → Result 10 (DP home to first)."""
base_state.current_on_base_code = 7
base_state.outs = 0
base_state.on_first = 2
base_state.on_second = 3
base_state.on_third = 4
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.on_third = create_runner(4)
base_state.is_runner_on_first = Mock(return_value=True)
base_state.is_runner_on_second = Mock(return_value=True)
base_state.is_runner_on_third = Mock(return_value=True)
@ -177,7 +188,7 @@ class TestChartLookup:
"""Runner on 3rd, GBA, Corners In, hit to 3B → Uses Infield In rules."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -194,7 +205,7 @@ class TestChartLookup:
"""Runner on 3rd, GBA, Corners In, hit to SS → Uses Infield Back rules (Result 5 → Result 3)."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -238,9 +249,9 @@ class TestResult1:
"""All runners stay put."""
base_state.current_on_base_code = 7 # Loaded
base_state.outs = 2 # Forces result 1
base_state.on_first = 2
base_state.on_second = 3
base_state.on_third = 4
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.on_third = create_runner(4)
base_state.is_runner_on_first = Mock(return_value=True)
base_state.is_runner_on_second = Mock(return_value=True)
base_state.is_runner_on_third = Mock(return_value=True)
@ -270,8 +281,8 @@ class TestResult2:
"""Successful DP: runner on 1st and batter both out."""
base_state.current_on_base_code = 4 # 1st and 2nd
base_state.outs = 0
base_state.on_first = 2
base_state.on_second = 3
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.is_runner_on_first = Mock(return_value=True)
base_state.is_runner_on_second = Mock(return_value=True)
@ -303,7 +314,7 @@ class TestResult2:
"""Failed DP: only force out at 2nd, batter safe."""
base_state.current_on_base_code = 1 # Runner on 1st
base_state.outs = 0
base_state.on_first = 2
base_state.on_first = create_runner(2)
base_state.is_runner_on_first = Mock(return_value=True)
result = advancement.advance_runners(
@ -333,7 +344,7 @@ class TestResult3:
"""Runner on 1st advances to 2nd."""
base_state.current_on_base_code = 1
base_state.outs = 0
base_state.on_first = 2
base_state.on_first = create_runner(2)
base_state.is_runner_on_first = Mock(return_value=True)
result = advancement.advance_runners(
@ -355,7 +366,7 @@ class TestResult3:
"""Runner on 3rd scores."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -381,7 +392,7 @@ class TestResult5:
"""Hit to 2B/SS: runners advance."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -398,7 +409,7 @@ class TestResult5:
"""Hit to corner: runners hold."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -421,9 +432,9 @@ class TestResult7:
"""Bases loaded, Infield In, GBC: Result 7/8 - forced advancement only."""
base_state.current_on_base_code = 7 # Bases loaded
base_state.outs = 0
base_state.on_first = 2
base_state.on_second = 3
base_state.on_third = 4
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.on_third = create_runner(4)
base_state.is_runner_on_first = Mock(return_value=True)
base_state.is_runner_on_second = Mock(return_value=True)
base_state.is_runner_on_third = Mock(return_value=True)
@ -443,7 +454,7 @@ class TestResult7:
"""Runner on 3rd only (not forced): holds."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -468,9 +479,9 @@ class TestResult10:
"""Successful DP: R3 out at home, batter out."""
base_state.current_on_base_code = 7
base_state.outs = 0
base_state.on_first = 2
base_state.on_second = 3
base_state.on_third = 4
base_state.on_first = create_runner(2)
base_state.on_second = create_runner(3)
base_state.on_third = create_runner(4)
base_state.is_runner_on_first = Mock(return_value=True)
base_state.is_runner_on_second = Mock(return_value=True)
base_state.is_runner_on_third = Mock(return_value=True)
@ -508,7 +519,7 @@ class TestResult12:
"""Hit to 1B: Simple advancement (Result 3)."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -525,7 +536,7 @@ class TestResult12:
"""Hit to 3B: Runners hold (Result 1)."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -542,7 +553,7 @@ class TestResult12:
"""Hit to SS/P/C: DECIDE opportunity (conservative default)."""
base_state.current_on_base_code = 3
base_state.outs = 0
base_state.on_third = 2
base_state.on_third = create_runner(2)
base_state.is_runner_on_third = Mock(return_value=True)
result = advancement.advance_runners(
@ -690,11 +701,11 @@ class TestEdgeCases:
base_state.is_runner_on_third = Mock(return_value=code in [3, 5, 6, 7])
if code in [1, 4, 5, 7]:
base_state.on_first = 2
base_state.on_first = create_runner(2)
if code in [2, 4, 6, 7]:
base_state.on_second = 3
base_state.on_second = create_runner(3)
if code in [3, 5, 6, 7]:
base_state.on_third = 4
base_state.on_third = create_runner(4)
result = advancement.advance_runners(
outcome=PlayOutcome.GROUNDBALL_A,

View File

@ -201,7 +201,8 @@ class TestStateManagerGetUpdate:
game_id=fake_id,
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
with pytest.raises(ValueError, match="not found"):

View File

@ -32,6 +32,7 @@ class TestGameStateValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status="active"
)
@ -46,6 +47,7 @@ class TestGameStateValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status="pending"
)
@ -63,6 +65,7 @@ class TestGameStateValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status="completed"
)
@ -163,6 +166,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
runners=[]
)
decision = DefensiveDecision(
@ -207,6 +211,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = DefensiveDecision(
@ -224,7 +229,8 @@ class TestDefensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
decision = DefensiveDecision(
alignment="normal",
@ -245,6 +251,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = DefensiveDecision(
@ -266,6 +273,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="LF", batting_order=3)
@ -286,6 +294,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = DefensiveDecision(
@ -306,6 +315,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="LF", batting_order=3)
)
decision = DefensiveDecision(
@ -323,6 +333,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2)
)
decision = DefensiveDecision(
@ -343,6 +354,7 @@ class TestDefensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="LF", batting_order=3)
@ -361,7 +373,8 @@ class TestDefensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
valid_alignments = ["normal", "shifted_left", "shifted_right", "extreme_shift"]
@ -377,7 +390,8 @@ class TestDefensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
valid_depths = ["in", "normal"]
@ -398,6 +412,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=0
)
decision = OffensiveDecision(approach="normal")
@ -423,6 +438,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = OffensiveDecision(
@ -440,7 +456,8 @@ class TestOffensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
decision = OffensiveDecision(
approach="normal",
@ -461,6 +478,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=2
)
decision = OffensiveDecision(
@ -484,8 +502,9 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=outs
)
)
decision = OffensiveDecision(
approach="normal",
bunt_attempt=True
@ -502,6 +521,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2)
)
decision = OffensiveDecision(
@ -519,6 +539,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="LF", batting_order=3)
)
decision = OffensiveDecision(
@ -536,6 +557,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2)
)
@ -566,6 +588,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = OffensiveDecision(
@ -585,7 +608,8 @@ class TestOffensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
decision = OffensiveDecision(
hit_and_run=True
@ -604,6 +628,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
decision = OffensiveDecision(
@ -621,6 +646,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="SS", batting_order=2)
)
decision = OffensiveDecision(
@ -638,6 +664,7 @@ class TestOffensiveDecisionValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="LF", batting_order=3)
)
decision = OffensiveDecision(
@ -654,7 +681,8 @@ class TestOffensiveDecisionValidation:
game_id=uuid4(),
league_id="sba",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
valid_approaches = ["normal", "contact", "power", "patient"]
@ -779,8 +807,9 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=outs
)
)
assert validator.can_continue_inning(state) is True
def test_cannot_continue_inning_with_three_outs(self):
@ -792,6 +821,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=2
)
# Simulate third out being recorded (outs goes to 3 temporarily)
@ -807,6 +837,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=8,
half="bottom",
home_score=5,
@ -823,6 +854,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="bottom",
home_score=5,
@ -839,6 +871,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="bottom",
home_score=5,
@ -855,6 +888,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="top",
home_score=5,
@ -871,6 +905,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=12,
half="bottom",
home_score=8,
@ -887,6 +922,7 @@ class TestGameFlowValidation:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=15,
half="bottom",
home_score=10,

View File

@ -206,7 +206,7 @@ class TestDefensiveDecision:
def test_defensive_decision_valid_infield_depths(self):
"""Test all valid infield depths"""
valid = ['in', 'normal', 'back', 'double_play']
valid = ['infield_in', 'normal', 'corners_in']
for depth in valid:
decision = DefensiveDecision(infield_depth=depth)
assert decision.infield_depth == depth
@ -283,8 +283,9 @@ class TestGameState:
game_id=game_id,
league_id="sba",
home_team_id=1,
away_team_id=2
)
away_team_id=2,
current_batter_lineup_id=1
)
assert state.game_id == game_id
assert state.league_id == "sba"
assert state.home_team_id == 1
@ -304,7 +305,8 @@ class TestGameState:
game_id=game_id,
league_id=league,
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
assert state.league_id == league
@ -316,7 +318,8 @@ class TestGameState:
game_id=game_id,
league_id="invalid",
home_team_id=1,
away_team_id=2
away_team_id=2,
current_batter_lineup_id=1
)
def test_game_state_valid_statuses(self):
@ -328,6 +331,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status=status
)
assert state.status == status
@ -341,6 +345,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status="invalid"
)
@ -353,6 +358,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half=half
)
assert state.half == half
@ -366,6 +372,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="middle"
)
@ -380,6 +387,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=outs
)
assert state.outs == outs
@ -391,6 +399,7 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=3
)
@ -404,8 +413,9 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="top"
)
)
assert state.get_batting_team_id() == 2
# Bottom of inning - home team bats
@ -422,8 +432,9 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="top"
)
)
assert state.get_fielding_team_id() == 1
# Bottom of inning - away team fields
@ -438,9 +449,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="SS", batting_order=3)
)
)
assert state.is_runner_on_first() is True
assert state.is_runner_on_second() is False
@ -454,9 +466,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="RF", batting_order=2)
)
)
runner = state.get_runner_at_base(1)
assert runner is not None
@ -473,9 +486,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_third=LineupPlayerState(lineup_id=3, card_id=103, position="SS", batting_order=3)
)
)
bases = state.bases_occupied()
assert bases == [1, 3]
@ -488,9 +502,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1),
on_second=LineupPlayerState(lineup_id=2, card_id=102, position="RF", batting_order=2)
)
)
assert len(state.get_all_runners()) == 2
state.clear_bases()
@ -506,8 +521,9 @@ class TestGameState:
game_id=game_id,
league_id="sba",
home_team_id=1,
away_team_id=2
)
away_team_id=2,
current_batter_lineup_id=1
)
player = LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
state.add_runner(player=player, base=1)
@ -522,8 +538,9 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
new_player = LineupPlayerState(lineup_id=2, card_id=102, position="RF", batting_order=2)
state.add_runner(player=new_player, base=1)
@ -539,8 +556,9 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
state.advance_runner(from_base=1, to_base=2)
assert state.is_runner_on_first() is False
@ -554,9 +572,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="top",
on_third=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
initial_score = state.away_score
state.advance_runner(from_base=3, to_base=4)
@ -573,9 +592,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="top",
on_third=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
state.advance_runner(from_base=3, to_base=4)
assert state.away_score == 1
assert state.home_score == 0
@ -586,9 +606,10 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
half="bottom",
on_third=LineupPlayerState(lineup_id=5, card_id=105, position="RF", batting_order=5)
)
)
state.advance_runner(from_base=3, to_base=4)
assert state.home_score == 1
assert state.away_score == 0
@ -601,8 +622,9 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
outs=0
)
)
assert state.increment_outs() is False # 1 out - not end of inning
assert state.outs == 1
@ -621,11 +643,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=3,
half="top",
outs=2,
on_first=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
state.end_half_inning()
assert state.inning == 3 # Same inning
@ -641,11 +664,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=3,
half="bottom",
outs=2,
on_second=LineupPlayerState(lineup_id=1, card_id=101, position="CF", batting_order=1)
)
)
state.end_half_inning()
assert state.inning == 4 # Next inning
@ -661,11 +685,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=5,
half="bottom",
home_score=5,
away_score=2
)
)
assert state.is_game_over() is False
@ -677,11 +702,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="bottom",
home_score=5,
away_score=2
)
)
assert state.is_game_over() is True
@ -693,11 +719,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="bottom",
home_score=2,
away_score=2
)
)
assert state.is_game_over() is False
@ -709,11 +736,12 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=10,
half="bottom",
home_score=5,
away_score=4
)
)
assert state.is_game_over() is True
@ -728,12 +756,13 @@ class TestGameState:
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=9,
half="bottom",
outs=0,
home_score=2,
away_score=5
)
)
# Game continues - home team gets chance to catch up
assert state.is_game_over() is False

View File

@ -32,6 +32,7 @@ async def test_create_new_game_success(game_commands):
league_id='sba',
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
inning=1,
half='top'
)
@ -64,6 +65,7 @@ async def test_create_new_game_with_pd_league(game_commands):
league_id='pd',
home_team_id=3,
away_team_id=5,
current_batter_lineup_id=1,
inning=1,
half='top'
)
@ -194,7 +196,7 @@ async def test_resolve_play_success(game_commands):
success = await game_commands.resolve_play(game_id)
assert success is True
mock_ge.resolve_play.assert_called_once_with(game_id)
mock_ge.resolve_play.assert_called_once_with(game_id, None)
mock_ge.get_game_state.assert_called_once_with(game_id)

View File

@ -41,6 +41,7 @@ def mock_game_state():
league_id="sba",
home_team_id=1,
away_team_id=2,
current_batter_lineup_id=1,
status="active",
inning=1,
half="top",