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

如何在JestJS中测试嵌套DOM元素的正确层级结构?

如何在Jest中验证元素存在且嵌套结构正确

我需要测试组件是否渲染出正确的嵌套菜单结构,预期的HTML结构如下:

<ul>
    <li>Menu 1</li>
    <li>Menu 2(Parent)
      <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li>Child 3 (Parent 2)
            <ul>
                  <li>Child 4</li>
                  <li>Child 5</li>
            </ul>
            </li>
      </ul>
    </li>
</ul>

我写了如下测试代码,但它只能验证元素存在,就算是下面这种完全没有嵌套的结构也能通过测试,不符合预期:

it('should render nested elements', () => {
    <MyComponent />
    expect(screen.getByText('Menu 1').toBeInDocument())
    expect(screen.getByText('Menu 2(Parent)').toBeInDocument())
    expect(screen.getByText('Child 3 (Parent 2)').toBeInDocument())
    expect(screen.getByText('Child 5').toBeInDocument())
}

错误的非嵌套结构示例:

<ul>
    <li>Menu 1</li>
    <li>Menu 2(Parent)</li>
   <li>Child 1</li>
   <li>Child 2</li>
   <li>Child 3 (Parent 2)</li>
   <li>Child 4</li>
   <li>Child 5</li>
</ul>

请问如何在Jest中同时验证元素存在且嵌套结构正确?


解决方法

方法1:用within限定查询范围,验证父子嵌套

利用Testing Library的within方法,先定位父级元素,再在父元素的范围内查询子元素,确保子元素确实嵌套在父元素内部。修改后的测试代码如下:

it('should render correctly nested menu structure', () => {
    // 补全render调用,原代码缺少这一步
    render(<MyComponent />);

    // 验证顶级元素Menu 1存在
    expect(screen.getByText('Menu 1')).toBeInTheDocument();

    // 获取Menu 2所在的<li>父元素
    const menu2ParentLi = screen.getByText('Menu 2(Parent)').closest('li');
    expect(menu2ParentLi).toBeInTheDocument();

    // 在Menu 2的父元素内查询子菜单,确保Child1、Child2是它的子元素
    within(menu2ParentLi).getByText('Child 1');
    within(menu2ParentLi).getByText('Child 2');

    // 获取Child 3所在的<li>父元素,再验证它的子元素Child4、Child5
    const child3ParentLi = within(menu2ParentLi).getByText('Child 3 (Parent 2)').closest('li');
    within(child3ParentLi).getByText('Child 4');
    within(child3ParentLi).getByText('Child 5');
});

方法2:通过role定位元素,验证层级结构

利用HTML元素的默认role(比如<ul>的role是list,<li>的role是listitem),逐层验证列表和列表项的嵌套关系:

it('should validate nested structure via roles', () => {
    render(<MyComponent />);

    // 获取顶级列表,验证顶级列表项数量
    const topLevelList = screen.getByRole('list');
    const topLevelItems = within(topLevelList).getAllByRole('listitem');
    expect(topLevelItems).toHaveLength(2); // 顶级应该有Menu1和Menu2两个项

    // 找到Menu2的列表项,获取它内部的子列表并验证子项数量
    const menu2Item = topLevelItems.find(item => item.textContent.includes('Menu 2(Parent)'));
    const firstChildList = within(menu2Item).getByRole('list');
    const firstChildItems = within(firstChildList).getAllByRole('listitem');
    expect(firstChildItems).toHaveLength(3); // 对应Child1、Child2、Child3

    // 找到Child3的列表项,验证它的子列表和子项数量
    const child3Item = firstChildItems.find(item => item.textContent.includes('Child 3 (Parent 2)'));
    const secondChildList = within(child3Item).getByRole('list');
    const secondChildItems = within(secondChildList).getAllByRole('listitem');
    expect(secondChildItems).toHaveLength(2); // 对应Child4、Child5
});

方法3:快照测试,快速验证整体结构

如果想一次性验证整个组件的渲染结构是否符合预期,可以使用Jest的快照测试:

it('should match nested structure snapshot', () => {
    const { container } = render(<MyComponent />);
    expect(container.firstChild).toMatchSnapshot();
});

首次运行会生成快照文件,后续测试会对比当前渲染结果与快照,结构变化时测试会直接失败,适合快速校验整体结构。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:13:15