从Enzyme迁移到React Testing Library:如何选择列表中的第n个元素
React Testing Library 选择第n个元素的实现方案
React Testing Library 没有提供和 Enzyme at() 完全对等的内置API,你可以通过以下两种方式实现相同需求:
方案1:结合带索引的data-testid实现(优先推荐,稳定性最高)
首先在业务组件代码中给对应元素添加带索引标识的data-testid:
// 年份头部按钮,index为循环渲染时的索引值 <button data-testid={`table-year-head-btn-${index}`}>...</button> // 月份容器 <div data-testid={`table-months-${index}`} className="table-months">...</div>
改造后的测试代码如下:
import { screen, fireEvent, within } from '@testing-library/react'; // 选中索引为1的年份头部按钮触发点击,对应原代码at(1)的逻辑 fireEvent.click(screen.getByTestId('table-year-head-btn-1')); // 选中索引为1的月份容器,查询容器内所有复选框 const secondMonthsContainer = screen.getByTestId('table-months-1'); const checkboxes = within(secondMonthsContainer).getAllByRole('checkbox'); checkboxes.forEach(checkbox => { expect(checkbox).toBeChecked(); });
方案2:直接取查询结果的数组下标(无需修改业务组件,适合快速迁移)
如果暂不想修改业务组件添加data-testid,也可以利用RTL所有*AllBy类查询返回DOM数组的特性,直接取下标实现选择:
import { screen, fireEvent, within } from '@testing-library/react'; // 查询年份头部的所有按钮,取下标为1的元素触发点击 const yearHeadBtns = within(screen.getByRole('region', { className: 'table-year-head' })).getAllByRole('button'); fireEvent.click(yearHeadBtns[1]); // 查询所有月份容器,取下标为1的容器,再查询内部复选框 const monthContainers = screen.getAllByRole('region', { className: 'table-months' }); const checkboxes = within(monthContainers[1]).getAllByRole('checkbox'); checkboxes.forEach(checkbox => { expect(checkbox).toBeChecked(); });
注意:两种方案的下标都是从0开始计数,和Enzyme at() 的计数规则完全一致。data-testid不会随样式、文案、业务逻辑的修改发生变化,优先使用方案1可以大幅降低测试用例的维护成本。
内容的提问来源于stack exchange,提问作者nick
相关产品推荐
相关产品推荐

