strat-gameplay-webapp/frontend-sba/tests/unit/store/game-decisions.spec.ts
Cal Corum 4e7ea9e514 CLAUDE: Remove alignment field from frontend - complete Session 1 cleanup
Removed all references to the defensive alignment field across frontend codebase
after backend removal in Session 1. The alignment field was determined to be unused
and was removed from DefensiveDecision model.

Changes:
- types/websocket.ts: Removed alignment from DefensiveDecisionRequest interface
- composables/useGameActions.ts: Removed alignment from submit handler
- pages/demo-decisions.vue: Updated demo state and summary text (alignment → depths)
- pages/games/[id].vue: Updated decision history text for both defensive and offensive
  * Defensive: Now shows "infield depth, outfield depth" instead of "alignment, infield"
  * Offensive: Updated to use new action field with proper labels (swing_away, hit_and_run, etc.)
- Test files (3): Updated all test cases to remove alignment references
  * tests/unit/composables/useGameActions.spec.ts
  * tests/unit/store/game-decisions.spec.ts
  * tests/unit/components/Decisions/DefensiveSetup.spec.ts

Also updated offensive decision handling to match Session 2 changes (approach/hit_and_run/bunt_attempt → action field).

Total: 7 files modified, all alignment references removed
Verified: Zero remaining alignment references in .ts/.vue/.js files

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 15:34:59 -06:00

224 lines
7.1 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useGameStore } from '~/store/game'
import type { DefensiveDecision, OffensiveDecision } from '~/types/game'
describe('Game Store - Decision Methods', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
describe('setPendingDefensiveSetup', () => {
it('sets defensive setup', () => {
const store = useGameStore()
const setup: DefensiveDecision = {
infield_depth: 'back',
outfield_depth: 'normal',
hold_runners: [1, 3],
}
store.setPendingDefensiveSetup(setup)
expect(store.pendingDefensiveSetup).toEqual(setup)
})
it('clears defensive setup with null', () => {
const store = useGameStore()
const setup: DefensiveDecision = {
infield_depth: 'normal',
outfield_depth: 'normal',
hold_runners: [],
}
store.setPendingDefensiveSetup(setup)
store.setPendingDefensiveSetup(null)
expect(store.pendingDefensiveSetup).toBeNull()
})
})
describe('setPendingOffensiveDecision', () => {
it('sets offensive decision', () => {
const store = useGameStore()
const decision: Omit<OffensiveDecision, 'steal_attempts'> = {
action: 'hit_and_run',
}
store.setPendingOffensiveDecision(decision)
expect(store.pendingOffensiveDecision).toEqual(decision)
})
it('clears offensive decision with null', () => {
const store = useGameStore()
const decision: Omit<OffensiveDecision, 'steal_attempts'> = {
action: 'swing_away',
}
store.setPendingOffensiveDecision(decision)
store.setPendingOffensiveDecision(null)
expect(store.pendingOffensiveDecision).toBeNull()
})
})
describe('setPendingStealAttempts', () => {
it('sets steal attempts', () => {
const store = useGameStore()
store.setPendingStealAttempts([2, 3])
expect(store.pendingStealAttempts).toEqual([2, 3])
})
it('updates steal attempts', () => {
const store = useGameStore()
store.setPendingStealAttempts([2])
store.setPendingStealAttempts([3, 4])
expect(store.pendingStealAttempts).toEqual([3, 4])
})
it('clears steal attempts with empty array', () => {
const store = useGameStore()
store.setPendingStealAttempts([2, 3, 4])
store.setPendingStealAttempts([])
expect(store.pendingStealAttempts).toEqual([])
})
})
describe('addDecisionToHistory', () => {
it('adds defensive decision to history', () => {
const store = useGameStore()
store.addDecisionToHistory('Defensive', 'normal infield, normal outfield')
expect(store.decisionHistory).toHaveLength(1)
expect(store.decisionHistory[0].type).toBe('Defensive')
expect(store.decisionHistory[0].summary).toBe('normal infield, normal outfield')
expect(store.decisionHistory[0].timestamp).toBeDefined()
})
it('adds offensive decision to history', () => {
const store = useGameStore()
store.addDecisionToHistory('Offensive', 'Hit & Run')
expect(store.decisionHistory).toHaveLength(1)
expect(store.decisionHistory[0].type).toBe('Offensive')
expect(store.decisionHistory[0].summary).toBe('Hit & Run')
})
it('adds new decisions to the front of history', () => {
const store = useGameStore()
store.addDecisionToHistory('Defensive', 'First decision')
store.addDecisionToHistory('Offensive', 'Second decision')
expect(store.decisionHistory[0].summary).toBe('Second decision')
expect(store.decisionHistory[1].summary).toBe('First decision')
})
it('limits history to 10 items', () => {
const store = useGameStore()
// Add 15 decisions
for (let i = 0; i < 15; i++) {
store.addDecisionToHistory('Defensive', `Decision ${i}`)
}
expect(store.decisionHistory).toHaveLength(10)
expect(store.decisionHistory[0].summary).toBe('Decision 14')
expect(store.decisionHistory[9].summary).toBe('Decision 5')
})
})
describe('clearPendingDecisions', () => {
it('clears all pending decisions', () => {
const store = useGameStore()
// Set all pending decisions
store.setPendingDefensiveSetup({
infield_depth: 'normal',
outfield_depth: 'normal',
hold_runners: [],
})
store.setPendingOffensiveDecision({
action: 'swing_away',
})
store.setPendingStealAttempts([2, 3])
// Clear all
store.clearPendingDecisions()
expect(store.pendingDefensiveSetup).toBeNull()
expect(store.pendingOffensiveDecision).toBeNull()
expect(store.pendingStealAttempts).toEqual([])
})
it('can be called multiple times safely', () => {
const store = useGameStore()
store.clearPendingDecisions()
store.clearPendingDecisions()
expect(store.pendingDefensiveSetup).toBeNull()
expect(store.pendingOffensiveDecision).toBeNull()
expect(store.pendingStealAttempts).toEqual([])
})
})
describe('resetGame', () => {
it('clears decision state on reset', () => {
const store = useGameStore()
// Set decisions and history
store.setPendingDefensiveSetup({
infield_depth: 'normal',
outfield_depth: 'normal',
hold_runners: [],
})
store.setPendingOffensiveDecision({
action: 'hit_and_run',
})
store.setPendingStealAttempts([2])
store.addDecisionToHistory('Defensive', 'test')
store.addDecisionToHistory('Offensive', 'test')
// Reset
store.resetGame()
expect(store.pendingDefensiveSetup).toBeNull()
expect(store.pendingOffensiveDecision).toBeNull()
expect(store.pendingStealAttempts).toEqual([])
expect(store.decisionHistory).toEqual([])
})
})
describe('Integration', () => {
it('handles complete decision workflow', () => {
const store = useGameStore()
// Set defensive decision
const defensiveSetup: DefensiveDecision = {
infield_depth: 'double_play',
outfield_depth: 'normal',
hold_runners: [1],
}
store.setPendingDefensiveSetup(defensiveSetup)
store.addDecisionToHistory('Defensive', 'double_play infield, normal outfield')
// Set offensive decision
const offensiveDecision: Omit<OffensiveDecision, 'steal_attempts'> = {
action: 'sac_bunt',
}
store.setPendingOffensiveDecision(offensiveDecision)
store.setPendingStealAttempts([])
store.addDecisionToHistory('Offensive', 'Sac Bunt')
// Verify all state
expect(store.pendingDefensiveSetup).toEqual(defensiveSetup)
expect(store.pendingOffensiveDecision).toEqual(offensiveDecision)
expect(store.pendingStealAttempts).toEqual([])
expect(store.decisionHistory).toHaveLength(2)
// Clear for next play
store.clearPendingDecisions()
expect(store.pendingDefensiveSetup).toBeNull()
expect(store.pendingOffensiveDecision).toBeNull()
expect(store.pendingStealAttempts).toEqual([])
expect(store.decisionHistory).toHaveLength(2) // History persists
})
})
})