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

问询enzyme、react-dom/test-tools或jsdom是否存在clientHeight相关已知缺陷

Enzyme/react-dom/test-tools/jsdom中clientHeight返回undefined的已知问题及解决办法

首先明确回答你的问题:是的,这类问题确实存在,核心原因在于jsdom(Enzyme的mount方法依赖它模拟DOM环境)并没有实现完整的浏览器布局渲染逻辑——它只会构建DOM树结构,但不会像真实浏览器那样计算元素的实际尺寸,这就导致clientHeight、offsetHeight这类需要布局计算的属性在测试环境中经常返回undefined或不正确的值。

为什么你的代码在浏览器里正常,测试里不行?

在真实浏览器中,组件挂载后浏览器会执行布局渲染,计算出元素的实际高度,clientHeight能拿到正确值;但在jsdom环境中,没有这个布局计算的过程,元素的尺寸属性默认不会被赋值,所以你的this.content.firstChild.clientHeight就成了undefined。

具体的解决方案

针对你的场景,这里有几种可行的处理方式:

1. 测试中手动模拟clientHeight的值

最简单的方式是在测试流程中,直接给目标DOM元素的clientHeight赋值,模拟真实浏览器的计算结果:

// Arrange
const wrapper = mount(
  <MyWidget trigger={<span>click me</span>} open={false}>
    <div style={{ height: 90, padding: 5 }}>Lorum Ipsum</div>
  </MyWidget>
);

// 找到内容容器的DOM实例,手动设置子元素的clientHeight
const contentDom = wrapper.find('#your-control-id').instance();
contentDom.firstChild.clientHeight = 100; // 对应你期望的90+5+5=100

// Act
wrapper.setProps({ open: true });

// Assert
expect(wrapper.children('div').prop('style')).to.have.property('maxHeight', 100);

2. 用jest spy模拟HTMLElement的clientHeight getter

如果不想在测试中逐一查找元素,也可以全局模拟clientHeight的获取逻辑:

// 在测试开始前模拟clientHeight
beforeEach(() => {
  jest.spyOn(HTMLElement.prototype, 'clientHeight', 'get').mockReturnValue(100);
});

// 测试结束后恢复原实现
afterEach(() => {
  jest.restoreAllMocks();
});

// 你的测试代码
test('should set correct maxHeight when open', () => {
  const wrapper = mount(
    <MyWidget trigger={<span>click me</span>} open={false}>
      <div style={{ height: 90, padding: 5 }}>Lorum Ipsum</div>
    </MyWidget>
  );
  
  wrapper.setProps({ open: true });
  
  expect(wrapper.children('div').prop('style')).to.have.property('maxHeight', 100);
});

3. 调整组件逻辑,减少对DOM尺寸的直接依赖

从长远来看,你可以重构组件逻辑,避免直接读取clientHeight:

  • 比如将子元素的高度通过props传递给MyWidget,这样测试时可以直接传入预期值;
  • 或者使用CSS的max-height过渡方案,结合overflow: hidden,不需要通过JS计算高度(比如设置max-height: 0和max-height: 1000px的过渡,来模拟展开收起效果)。

补充说明

这个问题并非Enzyme的缺陷,而是jsdom的设计限制——它的定位是模拟DOM API,而非实现完整的浏览器渲染引擎。react-dom/test-tools也依赖jsdom,所以同样会遇到这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:21:24