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

如何用Jest和React Testing Library测试窗口缩放时的CSS响应式样式

解决Jest/React Testing Library中响应式CSS媒体查询测试问题

你遇到的问题很典型:直接修改window.innerWidth并不会让浏览器自动重新计算媒体查询对应的CSS样式,因为Jest的JS DOM环境不会主动监听窗口尺寸变化并更新已渲染元素的样式。下面来一步步解决这个问题:

为什么你的测试不通过?

  1. 直接替换window对象无效:你用window = { ...window, innerWidth: 500 }的方式替换了全局window对象,但此时组件已经渲染完成,DOM不会重新读取新的window尺寸来应用媒体查询。
  2. 媒体查询需要触发样式重计算:即使修改了窗口尺寸,也需要触发resize事件或者重新渲染组件,才能让浏览器重新计算并应用对应的CSS规则。

正确的测试方案

我们需要先正确修改window.innerWidth(注意Jest中这个属性默认是只读的),然后触发样式重计算,再验证样式是否正确。这里有两种可靠的实现方式:

方式一:使用Object.defineProperty修改尺寸并触发resize事件

import { render } from '@testing-library/react';
import Footer from './Footer';

it("should toggle border display based on viewport width", () => {
  // 测试大屏幕尺寸(大于590px)
  Object.defineProperty(window, 'innerWidth', {
    writable: true,
    configurable: true,
    value: 1024
  });
  
  const { container } = render(<Footer />);
  let border = container.querySelector('.border');
  let computedStyle = window.getComputedStyle(border);
  
  // 验证大屏幕下border可见
  expect(computedStyle.display).not.toBe('none');

  // 修改为小屏幕尺寸(小于590px)
  Object.defineProperty(window, 'innerWidth', {
    writable: true,
    configurable: true,
    value: 500
  });
  
  // 触发resize事件,让JS DOM重新计算媒体查询样式
  window.dispatchEvent(new Event('resize'));
  
  // 重新获取元素和计算样式(因为resize可能触发组件更新)
  border = container.querySelector('.border');
  computedStyle = window.getComputedStyle(border);
  
  // 验证小屏幕下border被隐藏
  expect(computedStyle.display).toBe('none');
});

方式二:使用Jest Spy模拟尺寸并重新渲染组件

如果你更倾向于用Jest的mock能力,可以用jest.spyOn来模拟window.innerWidth,并通过重新渲染组件来应用新样式:

import { render } from '@testing-library/react';
import Footer from './Footer';

it("should hide border on small viewports", () => {
  // 保存原始窗口尺寸,测试后恢复
  const originalInnerWidth = window.innerWidth;
  
  // 模拟大屏幕尺寸
  const widthSpy = jest.spyOn(window, 'innerWidth', 'get').mockReturnValue(1024);
  
  const { container, rerender } = render(<Footer />);
  let border = container.querySelector('.border');
  expect(window.getComputedStyle(border).display).not.toBe('none');

  // 切换到小屏幕尺寸
  widthSpy.mockReturnValue(500);
  // 重新渲染组件,让它根据新的窗口尺寸应用样式
  rerender(<Footer />);

  // 验证样式变化
  border = container.querySelector('.border');
  expect(window.getComputedStyle(border).display).toBe('none');

  // 恢复原始窗口尺寸,避免影响其他测试
  widthSpy.mockRestore();
});

关键注意事项

  • 不要直接赋值window.innerWidth:Jest环境中window.innerWidth是只读属性,直接赋值不会生效,必须用Object.defineProperty或者jest.spyOn来修改。
  • 触发样式重计算:修改尺寸后,要么触发resize事件,要么重新渲染组件,才能让媒体查询的CSS规则生效。
  • 测试后恢复环境:记得在测试结束后恢复原始的window.innerWidth,避免影响其他测试用例的执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:31:42