import { describe, it, expect, afterEach } from 'vitest' import { ref } from 'vue' import { useRovingFocus } from '../src/lib/use-roving-focus' function makeItems(count: number) { const items = Array.from({ length: count }, (_, i) => { const el = document.createElement('button') el.textContent = `item-${i}` document.body.append(el) return el }) return items } function arrowDown() { return new KeyboardEvent('keydown', { key: 'ArrowDown', cancelable: true }) } function arrowUp() { return new KeyboardEvent('keydown', { key: 'ArrowUp', cancelable: true }) } describe('useRovingFocus', () => { afterEach(() => { document.body.replaceChildren() }) it('focusIndex focuses the item at that index', () => { const items = makeItems(3) const { focusIndex } = useRovingFocus(ref(items)) focusIndex(1) expect(document.activeElement).toBe(items[1]) }) it('focusIndex wraps by default when loop is not set', () => { const items = makeItems(3) const { focusIndex } = useRovingFocus(ref(items)) focusIndex(3) expect(document.activeElement).toBe(items[0]) focusIndex(-1) expect(document.activeElement).toBe(items[2]) }) it('focusIndex clamps instead of wrapping when loop is false', () => { const items = makeItems(3) const { focusIndex } = useRovingFocus(ref(items), { loop: false }) focusIndex(5) expect(document.activeElement).toBe(items[2]) focusIndex(-5) expect(document.activeElement).toBe(items[0]) }) it('handleKeydown moves focus forward/backward on ArrowDown/ArrowUp for vertical orientation', () => { const items = makeItems(3) const { handleKeydown } = useRovingFocus(ref(items)) items[0]!.focus() handleKeydown(arrowDown()) expect(document.activeElement).toBe(items[1]) handleKeydown(arrowUp()) expect(document.activeElement).toBe(items[0]) }) it('handleKeydown jumps to first/last on Home/End', () => { const items = makeItems(3) const { handleKeydown } = useRovingFocus(ref(items)) items[1]!.focus() handleKeydown(new KeyboardEvent('keydown', { key: 'End', cancelable: true })) expect(document.activeElement).toBe(items[2]) handleKeydown(new KeyboardEvent('keydown', { key: 'Home', cancelable: true })) expect(document.activeElement).toBe(items[0]) }) })