import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; import ChordPickerPopup from './ChordPickerPopup'; describe('ChordPickerPopup', () => { it('parses text input on enter and syncs the related buttons', () => { const onChange = vi.fn(); render(); const input = screen.getByRole('textbox'); fireEvent.change(input, { target: { value: 'Bm7b5' } }); fireEvent.keyDown(input, { key: 'Enter' }); expect(onChange).toHaveBeenCalledWith('Bm7b5'); expect(screen.getByRole('button', { name: 'Dim' }).className).toContain('selected'); expect(screen.getByRole('button', { name: 'b5' }).className).toContain('selected'); expect(screen.getByRole('button', { name: '7' }).className).toContain('selected'); }); it('shows an inline error for invalid text without mutating the region', () => { const onChange = vi.fn(); render(); const input = screen.getByRole('textbox'); fireEvent.change(input, { target: { value: 'invalid' } }); fireEvent.keyDown(input, { key: 'Enter' }); expect(onChange).not.toHaveBeenCalled(); expect(screen.getByText('Unable to parse chord')).toBeInTheDocument(); }); it('intercepts tab and delegates popup bar navigation', () => { const onTabNavigate = vi.fn(); render(); fireEvent.keyDown(screen.getByRole('textbox'), { key: 'Tab' }); expect(onTabNavigate).toHaveBeenCalledWith('forward'); }); it('intercepts shift-tab and delegates backward popup bar navigation', () => { const onTabNavigate = vi.fn(); render(); fireEvent.keyDown(screen.getByRole('textbox'), { key: 'Tab', shiftKey: true }); expect(onTabNavigate).toHaveBeenCalledWith('backward'); }); it('focuses the chord input when the popup opens', () => { render(); expect(screen.getByRole('textbox')).toHaveFocus(); }); it('blocks tab navigation when the current input is invalid', () => { const onChange = vi.fn(); const onTabNavigate = vi.fn(); render(); const input = screen.getByRole('textbox'); fireEvent.change(input, { target: { value: 'invalid' } }); fireEvent.keyDown(input, { key: 'Tab' }); expect(onChange).not.toHaveBeenCalled(); expect(onTabNavigate).not.toHaveBeenCalled(); expect(screen.getByText('Unable to parse chord')).toBeInTheDocument(); }); });