You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Testing Library中触发shadcn/radix Select渲染Portal选项

测试shadcn Select组件时无法获取Portal渲染的选项问题

我开发了一个包含shadcn Select控件的组件,其中SelectTrigger组件的role为combobox,但最终生成的HTML是button元素。组件在浏览器中运行正常,但编写单元测试时遇到了问题:我需要验证5个预期选项是否按正确顺序显示且值符合预期。

之前用原生HTML select元素时,单元测试很简单——哪怕下拉框没展开,选项也会渲染在DOM里。但改用shadcn的Select组件后,选项通过Portal渲染,只有当下拉列表展开时才会出现在DOM中。

组件简化代码

import '@/components/scripture-ref-keyed-list.component.css';
import { ScriptureCheckDefinition, ScriptureItemDetail } from 'platform-bible-utils';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from './shadcn-ui/select';

export type ScriptureSrcItemDetail = ScriptureItemDetail & {
  /** Source/type of detail. Can be used for grouping. */
  source: string | ScriptureCheckDefinition;
};

const scrBookColId = 'scrBook';
const typeColId = 'source';

export default function ScriptureRefKeyedList() {
  // Define possible grouping options
  const scrBookGroupName = 'one';
  const typeGroupName = 'two';

  const groupingOptions = [
    { label: 'No Grouping', value: [] },
    { label: `Group by ${scrBookGroupName}`, value: [scrBookColId] },
    { label: `Group by ${typeGroupName}`, value: [typeColId] },
    { label: `Group by ${scrBookGroupName} and ${typeGroupName}`, value: [scrBookColId, typeColId], },
    { label: `Group by ${typeGroupName} and ${scrBookGroupName}`, value: [typeColId, scrBookColId], },
  ];

  const handleSelectChange = (selectedGrouping: string) => {
    console.log(selectedGrouping);
  };

  return (
    <Select value={JSON.stringify([])} onValueChange={(value) => { handleSelectChange(value); }} >
      <SelectTrigger className="pr-mb-1">
        <SelectValue />
      </SelectTrigger>
      <SelectContent position="item-aligned">
        <SelectGroup>
          {groupingOptions.map((option) => (
            <SelectItem key={option.label} value={JSON.stringify(option.value)}>
              {option.label}
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  );
}

单元测试代码

import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import ScriptureRefKeyedList from '@/components/scripture-ref-keyed-list.component';

describe('ScriptureRefKeyedList default display mode (with combobox for grouping option)', () => {
  beforeEach(() => { render(<ScriptureRefKeyedList />); });

  it('should show grouping drop-down when clicked', async () => {
    const dropDown = screen.getByRole('combobox');
    // Check that No Grouping is the current (default) option:
    expect(screen.getByText('No Grouping')).toBeInTheDocument();

    expect(fireEvent.click(dropDown)).toBeTruthy();

    await waitFor(() => {
      expect(screen.findByText('Group by one')).toBeInTheDocument();
    });
  });
});

已尝试的解决方案

  • 用fireEvent和userEvent触发多种浏览器中有效的事件:click、mouseDown,设置焦点后按下箭头键
  • 尝试多种元素查询方式:getByRole('option')、getByText、findByText,并通过调试器断点检查DOM
  • 测试多种等待DOM更新的方法:await + waitFor、await + screen.findBy...、调整超时时间、await new Promise(r=>setTimeout(()=>r(), 0))、用act包裹操作

但无论尝试哪种方法,单元测试中的DOM都不会更新,除了默认选项“No Grouping”始终存在,查找其他选项的尝试全部失败。我知道很多人遇到过类似问题,部分方案对他人有效,但我试过所有方法后仍未解决。

内容的提问来源于stack exchange,提问作者Tom Bogle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:52:03