2

这是我的代码示例

<div class="dropdown" data-testid="dropdown">
  <div class="option" data-testid="option">
   <b>[AF]</b> Afghanistan
  </div>
  <div class="option" data-testid="option">
   <b>[AL]</b> Albania
  </div>
  <div class="option" data-testid="option">
   <b>[DZ]</b> Algeria
  </div>
 </div>

我需要做的是通过其文本访问第一个元素以触发 userEvent.selectOptions

const dropdown = getByTestId('dropdown');
userEvent.selectOptions(dropdown, screen.getByText('[AF] Afghanistan'))

我得到的是:

TestingLibraryElementError:无法找到带有以下文字的元素:[AF] 阿富汗。这可能是因为文本被多个元素分解。在这种情况下,您可以为您的文本匹配器提供一个功能,以使您的匹配器更加灵活。

这显然是因为我试图查询的文本被元素破坏了。

请注意,这不是一个选择/选项下拉菜单,它没有任何可访问的角色,所以我只能通过 screen.getByText 查询它

4

1 回答 1

2

getBy*查询接受TextMatch作为参数,这意味着参数可以是字符串、正则表达式或函数。在这种情况下,我们可以使用一个函数(而不是字符串)并定位我们想要选择的特定元素。

这是一个应用此逻辑并使其可重用的辅助函数。

const getByTextContent = (text) => {
    // Passing function to `getByText`
    return screen.getByText((content, element) => {
        const hasText = element => element.textContent === text
        const elementHasText = hasText(element)
        const childrenDontHaveText = Array.from(element?.children || []).every(child => !hasText(child))
        return elementHasText && childrenDontHaveText
  })
}

快速解释发生了什么:查询将遍历 DOM 中的所有元素,但我们希望避免返回超出需要的元素。我们确保没有一个孩子与它的父母有相同的文本。这确保我们返回的元素是实际包含目标文本的元素。

然后getByTextContent可以在您的测试中使用辅助函数,如下所示。

const dropdown = getByTestId('dropdown');
userEvent.selectOptions(dropdown, getByTextContent('[AF] Afghanistan'))
于 2021-07-18T13:50:45.543 回答