import { describe, expect, it, vi } from 'vitest'; import { createShortcutHandler, eventMatchesShortcut, isEditableElement, normaliseShortcutString, } from './keyboard'; describe('keyboard shortcut utilities', () => { it('normalises shortcut strings with aliases and stable modifier order', () => { expect(normaliseShortcutString('Shift + Cmd + K')).toBe('shift+meta+k'); expect(normaliseShortcutString('Control + Alt + ArrowLeft')).toBe('ctrl+alt+arrowleft'); expect(normaliseShortcutString('CommandOrControl + Space')).toBe('mod+space'); }); it('matches platform-specific mod shortcuts', () => { const macEvent = new KeyboardEvent('keydown', { key: 'k', metaKey: true, }); const windowsEvent = new KeyboardEvent('keydown', { key: 'k', ctrlKey: true, }); expect(eventMatchesShortcut(macEvent, 'mod+k', { platform: 'MacIntel' })).toBe(true); expect(eventMatchesShortcut(windowsEvent, 'mod+k', { platform: 'Win32' })).toBe(true); }); it('guards editable fields by default', () => { const input = document.createElement('input'); input.type = 'text'; document.body.appendChild(input); expect(isEditableElement(input)).toBe(true); input.remove(); }); it('does not run global shortcuts while typing in form fields', () => { const input = document.createElement('input'); input.type = 'text'; document.body.appendChild(input); const callback = vi.fn(); const handler = createShortcutHandler([ { id: 'search', keys: 'ctrl+k', handler: callback, }, ]); input.addEventListener('keydown', handler); input.dispatchEvent( new KeyboardEvent('keydown', { key: 'k', ctrlKey: true, bubbles: true, }), ); expect(callback).not.toHaveBeenCalled(); input.removeEventListener('keydown', handler); input.remove(); }); it('runs matching shortcuts outside editable fields', () => { const callback = vi.fn(); const handler = createShortcutHandler([ { id: 'play-pause', keys: ['space', 'k'], handler: callback, }, ]); document.body.addEventListener('keydown', handler); document.body.dispatchEvent( new KeyboardEvent('keydown', { key: ' ', bubbles: true, }), ); expect(callback).toHaveBeenCalledTimes(1); document.body.removeEventListener('keydown', handler); }); });