import { fireEvent } from '@testing-library/react' /** Exercise the visible menu while selecting the same value that the form will submit. */ export function selectOption(control: HTMLElement, value: string) { const native = control.tagName === 'SELECT' ? control as HTMLSelectElement : control.parentElement?.querySelector('select') if (!native) throw new Error('选择控件没有表单字段') if (control.tagName === 'SELECT') return fireEvent.change(control, { target: { value } }) const options = Array.from(native.options).filter((option) => !option.hidden) const index = options.findIndex((option) => option.value === value) if (index < 0) throw new Error(`没有可选值:${value}`) const menu = openSelect(control) const option = menu?.querySelector(`[data-option-index="${index}"]`) if (!option) throw new Error(`菜单没有可选值:${value}`) fireEvent.click(option) } /** Text and file fields continue to use change; custom single selects use their real menu. */ export function changeField(element: Parameters[0], init: Parameters[1]) { if (element instanceof HTMLElement && element.getAttribute('role') === 'combobox' && element.tagName === 'BUTTON') { return selectOption(element, String((init as { target?: { value?: unknown } })?.target?.value ?? '')) } return fireEvent.change(element, init) } export function openSelect(control: HTMLElement) { if (control.getAttribute('aria-expanded') !== 'true') { fireEvent.pointerDown(control); fireEvent.click(control) } const menu = document.getElementById(control.getAttribute('aria-controls')!) if (!menu) throw new Error('菜单未展开') return menu }