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>
224 lines
7.1 KiB
TypeScript
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
|
|
})
|
|
})
|
|
})
|