如何在Jest中获取document.body样式?如何测试useEffect中的代码?
在Jest中测试document.body样式与useEffect逻辑
一、在Jest中获取document.body的样式
Jest基于jsdom模拟浏览器环境,你可以通过两种方式获取document.body的样式:
- 获取内联样式:直接访问
document.body.style.xxx,比如document.body.style.overflow就能拿到代码里设置的内联overflow值。 - 获取计算后样式:如果要获取最终生效的样式(比如继承或CSS类设置的),用
window.getComputedStyle(document.body).xxx,比如window.getComputedStyle(document.body).overflow。
二、测试目标useEffect的逻辑
先把要测试的代码整理出来:
useEffect(() => { let top = 10; if (window.innerWidth > frame.current.clientHeight) { top = Math.max(top, (window.innerHeight - frame.current.clientHeight) / 2 - top); } frame.current.style.marginTop = `${top}px`; document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = 'auto'; } }, []); // 假设依赖为空,实际根据组件依赖调整
测试步骤与用例
1. 基础准备
Jest自带jsdom环境,不用额外配置。核心是模拟frame这个ref、窗口的innerWidth和innerHeight属性,以及组件的挂载/卸载流程。
2. 测试窗口宽度≤frame高度的场景
import { render, cleanup } from '@testing-library/react'; import YourComponent from './YourComponent'; // 每次测试后清理DOM,避免污染 afterEach(cleanup); test('窗口宽度小于等于frame高度时,设置正确marginTop并隐藏body滚动', () => { // 模拟frame ref const mockFrameRef = { current: { clientHeight: 500, style: {} } }; // 模拟窗口尺寸 Object.defineProperty(window, 'innerWidth', { value: 400 }); Object.defineProperty(window, 'innerHeight', { value: 800 }); // 渲染组件,这里假设组件通过props接收ref,实际根据组件结构调整 render(<YourComponent frameRef={mockFrameRef} />); // 验证marginTop为初始值10px expect(mockFrameRef.current.style.marginTop).toBe('10px'); // 验证body的overflow被设为hidden expect(document.body.style.overflow).toBe('hidden'); });
3. 测试窗口宽度>frame高度的场景
test('窗口宽度大于frame高度时,计算正确的marginTop并隐藏body滚动', () => { const mockFrameRef = { current: { clientHeight: 500, style: {} } }; Object.defineProperty(window, 'innerWidth', { value: 600 }); Object.defineProperty(window, 'innerHeight', { value: 800 }); render(<YourComponent frameRef={mockFrameRef} />); // 计算预期top值:(800-500)/2 -10 = 140,Math.max(10,140)=140 expect(mockFrameRef.current.style.marginTop).toBe('140px'); expect(document.body.style.overflow).toBe('hidden'); });
4. 测试组件卸载时恢复body滚动
test('组件卸载时,恢复body的overflow为auto', () => { const mockFrameRef = { current: { clientHeight: 500, style: {} } }; Object.defineProperty(window, 'innerWidth', { value: 400 }); // 拿到unmount方法,用于主动卸载组件 const { unmount } = render(<YourComponent frameRef={mockFrameRef} />); // 执行卸载 unmount(); // 验证overflow恢复为auto expect(document.body.style.overflow).toBe('auto'); });
注意事项
- 如果
frame是组件内部用useRef创建的,给frame元素加data-testid="frame",然后通过screen.getByTestId('frame')获取元素,再用Object.defineProperty模拟它的clientHeight。 - 窗口属性必须用
Object.defineProperty模拟,直接赋值window.innerWidth不会生效,因为这些是只读属性。 - 确保测试用例之间相互独立,避免残留状态影响结果。
内容的提问来源于stack exchange,提问作者fabralbert
相关产品推荐
相关产品推荐

