/** * Tests for SkillHotkeysHud, speedbars, keybindings, and Attack slot binding (Issue #151). */ import { describe, expect, it, beforeEach } from 'vitest' import { SkillHotkeysHud, LEFT_SKILL_BOUNDS, RIGHT_SKILL_BOUNDS, DEFAULT_SORCERESS_SKILLS, resolveSkillIcon, getAvailableSkillsForSide, } from '../src/ui/hotkeys.ts' describe('SkillHotkeysHud & Dual Slot Mechanics', () => { let hud: SkillHotkeysHud beforeEach(() => { hud = new SkillHotkeysHud() }) it('initializes with expected default skills and state', () => { expect(hud.leftSkillId).toBe(47) // Fire Ball expect(hud.rightSkillId).toBe(64) // Frozen Orb expect(hud.selectionOpen).toBeNull() expect(hud.availableSkills.length).toBeGreaterThanOrEqual(10) // Skill 0 is available const attack = hud.availableSkills.find((s) => s.skillId === 0) expect(attack).toBeDefined() expect(attack!.leftUsable).toBe(true) expect(attack!.rightUsable).toBe(true) }) it('opens and closes left selection speedbar on click', () => { // Click center of left skill icon const leftX = LEFT_SKILL_BOUNDS.x + 24 const leftY = LEFT_SKILL_BOUNDS.y + 24 const handled = hud.handleClick(leftX, leftY) expect(handled).toBe(true) expect(hud.selectionOpen).toBe('left') // Click again to close hud.handleClick(leftX, leftY) expect(hud.selectionOpen).toBeNull() }) it('opens and closes right selection speedbar on click', () => { // Click center of right skill icon const rightX = RIGHT_SKILL_BOUNDS.x + 24 const rightY = RIGHT_SKILL_BOUNDS.y + 24 const handled = hud.handleClick(rightX, rightY) expect(handled).toBe(true) expect(hud.selectionOpen).toBe('right') // Click outside to close hud.handleClick(100, 100) expect(hud.selectionOpen).toBeNull() }) it('allows selecting Normal Attack from left speedbar palette', () => { hud.openSpeedbar('left') expect(hud.selectionOpen).toBe('left') // Find Attack in speedbar layout const speedbarSkills = hud.getSpeedbarSkills('left') const attackEntry = speedbarSkills.find((e) => e.skill.skillId === 0) expect(attackEntry).toBeDefined() // Click on Attack icon in speedbar const clicked = hud.handleClick(attackEntry!.x + 10, attackEntry!.y + 10) expect(clicked).toBe(true) expect(hud.leftSkillId).toBe(0) expect(hud.selectionOpen).toBeNull() // closed after selection }) it('allows selecting Normal Attack from right speedbar palette', () => { hud.openSpeedbar('right') expect(hud.selectionOpen).toBe('right') const speedbarSkills = hud.getSpeedbarSkills('right') const attackEntry = speedbarSkills.find((e) => e.skill.skillId === 0) expect(attackEntry).toBeDefined() const clicked = hud.handleClick(attackEntry!.x + 10, attackEntry!.y + 10) expect(clicked).toBe(true) expect(hud.rightSkillId).toBe(0) expect(hud.selectionOpen).toBeNull() }) it('supports dual slot binding with Attack on both slots', () => { hud.assignSkill('left', 0) hud.assignSkill('right', 0) expect(hud.leftSkillId).toBe(0) expect(hud.rightSkillId).toBe(0) // Verify resolveSkillIcon works for both slots const leftIcon = resolveSkillIcon(hud.leftSkillId) const rightIcon = resolveSkillIcon(hud.rightSkillId) expect(leftIcon.skillId).toBe(0) expect(rightIcon.skillId).toBe(0) expect(leftIcon.name).toBe('Attack') expect(rightIcon.name).toBe('Attack') expect(leftIcon.iconPath).toBe('/skills/icon_0.png') expect(rightIcon.iconPath).toBe('/skills/icon_0.png') }) it('manages F1-F8 hotkey bindings and key presses', () => { // Bind F1 to Attack (0) hud.setHotkey('F1', 0) expect(hud.getHotkey('F1')).toBe(0) // Bind F2 to Frozen Orb (64) hud.setHotkey('F2', 64) expect(hud.getHotkey('F2')).toBe(64) // Pressing F1 assigns right skill to 0 const handledF1 = hud.handleKeyDown('F1') expect(handledF1).toBe(true) expect(hud.rightSkillId).toBe(0) // Pressing F2 assigns right skill to 64 const handledF2 = hud.handleKeyDown('F2') expect(handledF2).toBe(true) expect(hud.rightSkillId).toBe(64) }) it('handles mouse hover over skill buttons and speedbar icons', () => { hud.handleMouseMove(LEFT_SKILL_BOUNDS.x + 10, LEFT_SKILL_BOUNDS.y + 10) expect(hud.hoverSkillId).toBe(hud.leftSkillId) hud.handleMouseMove(RIGHT_SKILL_BOUNDS.x + 10, RIGHT_SKILL_BOUNDS.y + 10) expect(hud.hoverSkillId).toBe(hud.rightSkillId) hud.openSpeedbar('left') const speedbarSkills = hud.getSpeedbarSkills('left') const attackEntry = speedbarSkills.find((e) => e.skill.skillId === 0) expect(attackEntry).toBeDefined() hud.handleMouseMove(attackEntry!.x + 10, attackEntry!.y + 10) expect(hud.hoverSpeedbarSkillId).toBe(0) }) })