31 lines
1.7 KiB
TypeScript

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<HTMLElement>(`[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<typeof fireEvent.change>[0], init: Parameters<typeof fireEvent.change>[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
}