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

React Testing Library中自定义下拉框选择测试问题排查

React Testing Library测试自定义下拉框选择失效问题

我正在使用React Testing Library(RTL)测试自定义下拉框的选择功能,遇到了点击选项后值未更新的问题:点击选项后下拉框会关闭,但输入框中的选中值没有变化,预期的提示消息也未显示,导致测试断言失败。

调试细节

初始DOM结构

<div
  aria-expanded="false"
  aria-haspopup="true"
  aria-owns="contact-person_list"
  role="combobox"
>
  <button
    aria-hidden="true"
    class="hidden-control nofocus"
    tabindex="-1"
    type="button"
  />
  <span
    class="input-field input-field--active input-field--focus"
  >
    <span
      class="input-field__field"
    >
      <input
        aria-autocomplete="none"
        aria-controls="contact-person_list"
        aria-describedby=""
        aria-labelledby="contact-person_label"
        aria-readonly="true"
        autocomplete="off"
        class="input-field__input ellipsis"
        id="contact-person"
        readonly=""
        type="text"
        value="Passanger 1"
      />
    </span>
    <label
      aria-label="Contact Person"
      class="input-field__placeholder"
      for="contact-person"
      id="contact-person_label"
    >
      Contact Customer
    </label>
    <span
      class="input-field__chevron"
    >
      <span
        aria-hidden="true"
        class="pictogram-wrapper"
        dir="auto"
      >
        <i
          class="icon icon-chevron-down"
        />
      </span>
    </span>
  </span>
  
  <p
    aria-live="polite"
    class="auto-suggest__error-msg"
    role="region"
  />
</div>

打开下拉框的测试代码

const { getByRole, container, asFragment } = renderContactCardMock(passengerPersonEmptyMock);
await userEvent.click(getByRole('textbox', { name: 'Contact Customer' }));
expect(await screen.getByText('Travel Agent')).toBeInTheDocument(); // 确认下拉框已打开

下拉框打开后的DOM结构

<div
  class="popover pop-over hideDeskViewGroupListTitle enhanced-auto-suggest-v2-pop-over"
  data-auto="AutoSuggestFieldPopover"
  initialpositiondelay="0"
  style="width: 0px; top: 9px; left: 10px;"
  tabindex="-1"
>
  <div
    class="popover__arrow"
  />
  <div
    class="scroll scroll--visible"
  >
    <div
      class="scroll__box scroll__box--use-scroll"
    >
      <div>
        <div
          class="rich-text auto-suggest__group-list-title"
        >
          Contact Customer
        </div>
        <div
          class="auto-suggest modal-popover enhanced-auto-suggest-v2-popup"
          id="contact-person"
          role="listbox"
          tabindex="-1"
        >
          <div
            class="auto-suggest__list"
          >
            <button
              aria-selected="false"
              class="auto-suggest__item auto-suggest__highlight-selected-item"
              data-prevent-esc="true"
              role="option"
              type="button"
            >
              <div
                class="drop-down-item__dropdown"
              >
                <strong
                  class="drop-down-item__dropdown-name"
                >
                  Passenger 1
                </strong>
                <span
                  aria-hidden="true"
                  class="pictogram-wrapper"
                  dir="auto"
                >
                  <i
                    class="icon icon-check"
                  />
                </span>
              </div>
            </button>
            <button
              aria-selected="false"
              class="auto-suggest__item"
              data-prevent-esc="true"
              role="option"
              type="button"
            >
              <div
                class="drop-down-item__dropdown"
              >
                <strong
                  class="drop-down-item__dropdown-name"
                >
                  Travel Agent
                </strong>
              </div>
            </button>
          </div>
        </div>
      </div>
    </div>
    <div
      class="scroll__bar scroll__bar--visible"
    />
  </div>
</div>

选择选项的测试代码(断言失败)

await userEvent.click(screen.getByRole('option', {name : 'Travel Agent'}));
expect(screen.getByText("Travel agent should add registered contact number")).toBeInTheDocument(); // 执行失败

可能的排查方向

  • 检查userEvent版本:确保使用@testing-library/user-event的最新版本,旧版本对自定义组件的事件模拟可能存在兼容性问题。
  • 修正选项定位方式:选项的文本嵌套在<strong>标签中,getByRole('option', {name: 'Travel Agent'})可能无法准确匹配,尝试通过文本定位后再找到对应的按钮:
    const travelAgentOption = screen.getByText('Travel Agent').closest('button[role="option"]');
    await userEvent.click(travelAgentOption);
    
  • 等待状态异步更新:组件状态更新可能存在延迟,用waitFor包裹断言,确保状态更新完成后再检查:
    await waitFor(() => {
      expect(screen.getByText("Travel agent should add registered contact number")).toBeInTheDocument();
    });
    
  • 验证组件事件绑定:确认自定义下拉框的option按钮是否正确绑定了选择回调,点击时是否触发了onChange来更新父组件的选中值。
  • 模拟键盘交互:尝试用键盘模拟真实用户选择流程,看是否能触发值更新:
    await userEvent.click(getByRole('textbox', { name: 'Contact Customer' }));
    await userEvent.keyboard('{ArrowDown}{Enter}'); // 选中第二个选项并确认
    await waitFor(() => {
      expect(screen.getByText("Travel agent should add registered contact number")).toBeInTheDocument();
    });
    

内容的提问来源于stack exchange,提问作者Vivek Chauhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:12:28