71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
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])
|
|
})
|
|
})
|