import { describe, it, expect, vi, beforeEach } from 'vitest'; // Mock Phaser vi.mock('phaser', () => { class MockEventEmitter { on = vi.fn().mockReturnThis(); once = vi.fn().mockReturnThis(); emit = vi.fn().mockReturnThis(); off = vi.fn().mockReturnThis(); removeAllListeners = vi.fn().mockReturnThis(); } return { default: { Events: { EventEmitter: MockEventEmitter }, Scene: class { events = new MockEventEmitter(); add = { graphics: vi.fn(), sprite: vi.fn(), }; } } }; }); import { PlayerInputHandler } from '../PlayerInputHandler'; import type { CombatantActor, RangedWeaponItem } from '../../../core/types'; // Minimal mock for GameScene const createMockScene = () => { const scene = { gameInput: { on: vi.fn(), }, targetingSystem: { itemId: null, isActive: false, }, entityAccessor: { getPlayer: vi.fn(), }, runState: { lastReloadableWeaponId: null, }, startReload: vi.fn(), } as any; return scene; }; describe('Reload Last Used Weapon Logic', () => { let scene: any; let inputHandler: PlayerInputHandler; let reloadCallback: Function; beforeEach(() => { scene = createMockScene(); inputHandler = new PlayerInputHandler(scene); inputHandler.registerListeners(); // Find the reload listener const reloadCall = scene.gameInput.on.mock.calls.find((call: any[]) => call[0] === 'reload'); reloadCallback = reloadCall[1]; }); it('should reload the last reloadable weapon if nothing else is targeted or equipped', () => { const pistol: RangedWeaponItem = { id: 'pistol-1', name: 'Pistol', type: 'Weapon', weaponType: 'ranged', currentAmmo: 0, reloadingTurnsLeft: 0, stats: { attack: 1, range: 5, magazineSize: 6, ammoType: '9mm', projectileSpeed: 10 }, textureKey: 'weapons', spriteIndex: 0 }; const player: CombatantActor = { id: 1, pos: { x: 0, y: 0 }, category: 'combatant', isPlayer: true, type: 'player', inventory: { items: [pistol], gold: 0 }, equipment: { mainHand: { type: 'Weapon', weaponType: 'melee', id: 'sword-1' } as any }, stats: {} as any, energy: 100, speed: 100 }; scene.entityAccessor.getPlayer.mockReturnValue(player); scene.runState.lastReloadableWeaponId = 'pistol-1'; // Trigger reload (simulating 'R' press) reloadCallback(); expect(scene.startReload).toHaveBeenCalledWith(player, pistol); }); it('should prioritize targeted item over last used', () => { const pistol1: RangedWeaponItem = { id: 'p1', name: 'P1', type: 'Weapon', weaponType: 'ranged' } as any; const pistol2: RangedWeaponItem = { id: 'p2', name: 'P2', type: 'Weapon', weaponType: 'ranged' } as any; const player: CombatantActor = { id: 1, inventory: { items: [pistol1, pistol2] }, equipment: {} } as any; scene.entityAccessor.getPlayer.mockReturnValue(player); scene.targetingSystem.itemId = 'p2'; scene.runState.lastReloadableWeaponId = 'p1'; reloadCallback(); expect(scene.startReload).toHaveBeenCalledWith(player, pistol2); }); it('should prioritize equipped ranged weapon over last used', () => { const pistol1: RangedWeaponItem = { id: 'p1', name: 'P1', type: 'Weapon', weaponType: 'ranged' } as any; const pistol2: RangedWeaponItem = { id: 'p2', name: 'P2', type: 'Weapon', weaponType: 'ranged' } as any; const player: CombatantActor = { id: 1, inventory: { items: [pistol1, pistol2] }, equipment: { mainHand: pistol2 } } as any; scene.entityAccessor.getPlayer.mockReturnValue(player); scene.runState.lastReloadableWeaponId = 'p1'; reloadCallback(); expect(scene.startReload).toHaveBeenCalledWith(player, pistol2); }); it('should do nothing if no weapon is found', () => { const player: CombatantActor = { id: 1, inventory: { items: [] }, equipment: {} } as any; scene.entityAccessor.getPlayer.mockReturnValue(player); reloadCallback(); expect(scene.startReload).not.toHaveBeenCalled(); }); });