/** * test/keybar.test.ts — Unit tests for keybar module (T10). * * Tests the pure KEY_MAP data structure and verifies each key * is mapped to the correct byte string (ARCHITECTURE §5 / §6.3). * * Per task spec: "对纯字节表单测,DOM 部分手动验" — * We test the byte mappings here. DOM behavior (button creation, * event binding, touchstart vs click) is left to manual E2E verification * since jsdom is not in the project dependencies. */ import { describe, it, expect } from 'vitest' import { KEY_MAP } from '../public/keybar.js' describe('keybar', () => { describe('KEY_MAP — pure byte mappings', () => { it('exports KEY_MAP as a constant object', () => { expect(KEY_MAP).toBeDefined() expect(typeof KEY_MAP).toBe('object') }) it('Esc maps to \\x1b (0x1B)', () => { expect(KEY_MAP.esc).toBe('\x1b') expect(KEY_MAP.esc.charCodeAt(0)).toBe(0x1b) }) it('Shift+Tab maps to \\x1b[Z', () => { expect(KEY_MAP.shiftTab).toBe('\x1b[Z') expect(KEY_MAP.shiftTab).toHaveLength(3) expect(KEY_MAP.shiftTab.charCodeAt(0)).toBe(0x1b) expect(KEY_MAP.shiftTab.charCodeAt(1)).toBe('['.charCodeAt(0)) expect(KEY_MAP.shiftTab.charCodeAt(2)).toBe('Z'.charCodeAt(0)) }) it('arrow up maps to \\x1b[A', () => { expect(KEY_MAP.arrowUp).toBe('\x1b[A') expect(KEY_MAP.arrowUp).toHaveLength(3) }) it('arrow down maps to \\x1b[B', () => { expect(KEY_MAP.arrowDown).toBe('\x1b[B') expect(KEY_MAP.arrowDown).toHaveLength(3) }) it('arrow left maps to \\x1b[D', () => { expect(KEY_MAP.arrowLeft).toBe('\x1b[D') expect(KEY_MAP.arrowLeft).toHaveLength(3) }) it('arrow right maps to \\x1b[C', () => { expect(KEY_MAP.arrowRight).toBe('\x1b[C') expect(KEY_MAP.arrowRight).toHaveLength(3) }) it('Enter maps to \\r (0x0D carriage return, not \\n)', () => { expect(KEY_MAP.enter).toBe('\r') expect(KEY_MAP.enter).toHaveLength(1) expect(KEY_MAP.enter.charCodeAt(0)).toBe(0x0d) expect(KEY_MAP.enter).not.toBe('\n') expect(KEY_MAP.enter.charCodeAt(0)).not.toBe(0x0a) }) it('Ctrl+C maps to \\x03 (0x03 ETX)', () => { expect(KEY_MAP.ctrlC).toBe('\x03') expect(KEY_MAP.ctrlC).toHaveLength(1) expect(KEY_MAP.ctrlC.charCodeAt(0)).toBe(0x03) }) it('Tab maps to \\t (0x09)', () => { expect(KEY_MAP.tab).toBe('\t') expect(KEY_MAP.tab).toHaveLength(1) expect(KEY_MAP.tab.charCodeAt(0)).toBe(0x09) }) it('all 9 keys are defined', () => { const keys = Object.keys(KEY_MAP) expect(keys).toEqual([ 'esc', 'shiftTab', 'arrowUp', 'arrowDown', 'arrowLeft', 'arrowRight', 'enter', 'ctrlC', 'tab', ]) }) it('all mapped bytes are unique strings', () => { const bytes = Object.values(KEY_MAP) expect(bytes).toHaveLength(9) expect(new Set(bytes).size).toBe(9) // all unique }) it('ANSI arrow sequences use correct format', () => { // All arrow keys follow \x1b[X pattern where X is A/B/C/D const arrowKeys = [KEY_MAP.arrowUp, KEY_MAP.arrowDown, KEY_MAP.arrowLeft, KEY_MAP.arrowRight] arrowKeys.forEach((seq) => { expect(seq).toMatch(/^\x1b\[./) expect(seq).toHaveLength(3) }) }) }) })