【问题标题】:How to get element by proximity to another element in React Testing Library如何通过接近 React 测试库中的另一个元素来获取元素
【发布时间】:2020-07-17 22:57:19
【问题描述】:

我一直在尝试使用React Testing Library 并遵循他们的guiding principles 编写一些测试,因为这些测试应该以用户使用它的方式测试应用程序组件。

我有一个组件,它呈现一个对象列表,每个对象都有几个字段,从而产生一个像这样的 DOM:

<div>
  <h1>Fluffy</h1>
  <h2>Cat</h2>
  <span>3 years old</span>
</div>
<div>
  <h1>Oscar</h1>
  <h2>Cat</h2>
  <span>2 years old</span>
</div>
<div>
  <h1>Charlie</h1>
  <h2>Dog</h2>
  <span>3 years old</span>
</div>

我想断言每个对象都使用相关字段正确呈现,但我看不到如何使用 React 测试库来做到这一点。到目前为止,我有:

it('renders the animal names, species, and ages', () => {
  render(<MyAnimalsComponent />)

  const fluffyName = screen.getByRole('heading', { name: 'Fluffy' })
  expect(fluffyName).toBeInTheDocument()

  // The problem here is that there are multiple headings with the name "Cat" (Fluffy and Oscar) and I have no way of checking that the one that is returned is actually the one for Fluffy.
  const fluffySpecies = screen.getByRole('heading', { name: 'Cat' })
  expect(fluffySpecies).toBeInTheDocument()

  // Likewise, the age "3 years old" is rendered for both Fluffy and Charlie. How do I make sure I get the one that is rendered in the same container as Fluffy's name?
  const fluffyAge = screen.getByText('3 years old')
  expect(fluffyAge).toBeInTheDocument()
})

有没有办法使用 React 测试库中的查询方法来只查找与另一个元素有共同父级的元素?还是一种获取元素的父元素然后只查找该元素的子元素的方法?

在遵循 React 测试库的指导原则的同时,最好的方法是什么?

【问题讨论】:

    标签: html testing dom react-testing-library


    【解决方案1】:

    解决此问题的一种方法是使用顶级 getByRolegetByText 方法并传入一个元素作为第一个参数以将查询限制为该元素。

    对于我的示例,这涉及在一些包装元素上设置 role 属性,以便更容易地从语义上查找元素:

    <div role="list">
      <div role="listitem">
        <h1>Fluffy</h1>
        <h2>Cat</h2>
        <span>3 years old</span>
      </div>
      <div role="listitem">
        <h1>Oscar</h1>
        <h2>Cat</h2>
        <span>2 years old</span>
      </div>
      <div role="listitem">
        <h1>Charlie</h1>
        <h2>Dog</h2>
        <span>3 years old</span>
      </div>
    </div>
    

    然后在测试中,我找到了不同的列表项,然后对这些项进行了查询:

    import { render, screen, getByText, getByRole } from '@testing-library/react'
    
    it('renders the animal names, species, and ages', () => {
      render(<MyAnimalsComponent />)
    
      const animals = screen.getAllByRole('listitem')
    
      const fluffyName = getByRole(animals[0], 'heading', { name: 'Fluffy' })
      expect(fluffyName).toBeInTheDocument()
    
      const fluffySpecies = getByRole(animals[0], 'heading', { name: 'Cat' })
      expect(fluffySpecies).toBeInTheDocument()
    
      const fluffyAge = getByText(animals[0], '3 years old')
      expect(fluffyAge).toBeInTheDocument()
    })
    

    更新:同样的事情可以使用within 方法来完成,这可能更容易理解:

    import { render, screen, within } from '@testing-library/react'
    
    it('renders the animal names, species, and ages', () => {
      render(<MyAnimalsComponent />)
    
      const animals = screen.getAllByRole('listitem')
    
      const fluffyName = within(animals[0]).getByRole('heading', { name: 'Fluffy' })
      expect(fluffyName).toBeInTheDocument()
    
      const fluffySpecies = within(animals[0]).getByRole('heading', { name: 'Cat' })
      expect(fluffySpecies).toBeInTheDocument()
    
      const fluffyAge = within(animals[0]).getByText('3 years old')
      expect(fluffyAge).toBeInTheDocument()
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 2017-10-09
      • 1970-01-01
      相关资源
      最近更新 更多