| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /**
- * Radix UI Select组件的测试工具函数
- * 用于在测试中处理Radix UI Select组件的交互
- *
- * 注意:这个文件应该只在测试环境中使用,不要在生产代码中导入
- */
- import { screen } from '@testing-library/react';
- import userEvent from '@testing-library/user-event';
- /**
- * 查找Radix UI Select组件的隐藏select元素
- * Radix UI Select组件在DOM中会创建一个隐藏的select元素用于表单提交
- * 这个函数帮助我们在测试中找到这个隐藏的select元素
- *
- * @param selectButton - Select组件的触发按钮元素
- * @returns 隐藏的select元素,如果找不到则返回null
- */
- export function findHiddenSelectElement(selectButton: HTMLElement): HTMLSelectElement | null {
- // 在按钮的父元素或附近查找隐藏的select
- // 优先在按钮附近查找,如果找不到再全局查找
- const hiddenSelect = selectButton.closest('div')?.querySelector('select[data-radix-select-viewport]') ||
- selectButton.closest('div')?.querySelector('select[aria-hidden="true"]') ||
- selectButton.closest('div')?.querySelector('select[hidden]') ||
- document.querySelector('select[data-radix-select-viewport]') ||
- document.querySelector('select[aria-hidden="true"]') ||
- document.querySelector('select[hidden]');
- return hiddenSelect as HTMLSelectElement | null;
- }
- /**
- * 选择Radix UI Select组件的选项
- * 这个函数封装了查找隐藏select元素并选择选项的逻辑
- *
- * @param selectButton - Select组件的触发按钮元素
- * @param optionValue - 要选择的选项值
- * @returns 如果成功选择了选项返回true,否则返回false
- */
- export async function selectRadixOption(selectButton: HTMLElement, optionValue: string): Promise<boolean> {
- const hiddenSelect = findHiddenSelectElement(selectButton);
- if (hiddenSelect) {
- // 如果有隐藏的select,使用userEvent.selectOptions
- await userEvent.selectOptions(hiddenSelect, optionValue);
- return true;
- }
- return false;
- }
- /**
- * 通过test ID查找并选择Radix UI Select组件的选项
- * 这个函数封装了完整的查找、点击、选择流程
- *
- * @param testId - Select组件的test ID
- * @param optionValue - 要选择的选项值
- * @param user - userEvent实例(可选)
- * @returns 如果成功选择了选项返回true,否则返回false
- */
- export async function selectRadixOptionByTestId(
- testId: string,
- optionValue: string,
- user = userEvent
- ): Promise<boolean> {
- // 获取Select组件的触发按钮
- const selectButton = screen.getByTestId(testId);
- // 点击打开下拉菜单
- await user.click(selectButton);
- // 查找并选择选项
- return await selectRadixOption(selectButton, optionValue);
- }
- /**
- * 等待Radix UI Select组件启用
- * 有些Select组件在数据加载完成前是禁用的
- *
- * @param testId - Select组件的test ID
- * @param timeout - 超时时间(毫秒),默认5000ms
- */
- export async function waitForRadixSelectEnabled(testId: string, timeout = 5000): Promise<void> {
- const startTime = Date.now();
- while (Date.now() - startTime < timeout) {
- try {
- const selectElement = screen.getByTestId(testId);
- if (!selectElement.hasAttribute('disabled') && selectElement.getAttribute('aria-disabled') !== 'true') {
- return;
- }
- } catch (error) {
- // 元素可能还没渲染出来,继续等待
- }
- // 等待一小段时间再检查
- await new Promise(resolve => setTimeout(resolve, 100));
- }
- throw new Error(`Radix Select with testId "${testId}" did not become enabled within ${timeout}ms`);
- }
- /**
- * 完整的Radix UI Select选择流程
- * 包含等待启用、点击打开、选择选项的完整流程
- *
- * @param testId - Select组件的test ID
- * @param optionValue - 要选择的选项值
- * @param options - 配置选项
- * @param options.useFireEvent - 是否使用fireEvent而不是userEvent.click(默认为false)
- * @param options.user - userEvent实例(可选)
- */
- export async function completeRadixSelectFlow(
- testId: string,
- optionValue: string,
- options: {
- useFireEvent?: boolean;
- user?: typeof userEvent;
- } = {}
- ): Promise<void> {
- const { useFireEvent = false, user = userEvent } = options;
- // 1. 等待Select组件启用
- await waitForRadixSelectEnabled(testId);
- // 2. 获取Select按钮
- const selectButton = screen.getByTestId(testId);
- // 3. 点击打开下拉菜单
- if (useFireEvent) {
- // 有些Radix UI Select组件需要使用fireEvent而不是userEvent
- const { fireEvent } = await import('@testing-library/react');
- fireEvent.click(selectButton);
- } else {
- await user.click(selectButton);
- }
- // 4. 查找并选择选项
- const success = await selectRadixOption(selectButton, optionValue);
- if (!success) {
- // 如果通过隐藏select找不到,尝试直接点击选项文本
- // 注意:这里假设选项文本已经在DOM中渲染
- throw new Error(`Failed to select option "${optionValue}" for Radix Select with testId "${testId}". Make sure the dropdown is open and options are rendered.`);
- }
- }
|