如何在Jest测试中模拟鼠标左右拖动Split.js滑块的操作?
解决Split.js Jest测试中拖动模拟失败的问题
Split.js的拖动逻辑依赖完整的鼠标事件链(mousedown → mousemove → mouseup),且需要正确传递鼠标位置参数,同时它会监听document级别的mousemove/mouseup事件,而非仅gutter元素。以下是可行的模拟方案:
1. 获取关键元素
先定位Split.js自动生成的gutter元素,以及需要断言的左右容器:
// 优先用语义化选择器,也可直接用类名 const gutter = screen.getByRole('separator'); const leftPanel = document.getElementById('left-panel'); const rightPanel = document.getElementById('right-panel');
2. 模拟完整拖动事件链
按顺序触发事件,并为每个事件传入真实的鼠标坐标参数:
方案一:React Testing Library 实现
import { fireEvent, act } from '@testing-library/react'; // 1. 触发gutter的mousedown,传入初始鼠标位置 const gutterRect = gutter.getBoundingClientRect(); fireEvent.mouseDown(gutter, { clientX: gutterRect.left }); // 2. 模拟鼠标拖动到目标位置(向左拖200px,缩小左容器) act(() => { fireEvent.mouseMove(document, { clientX: gutterRect.left - 200 }); }); // 3. 触发mouseup完成拖动 fireEvent.mouseUp(document); // 4. 断言容器宽度变化 expect(leftPanel.style.width).toBeLessThan('50%'); expect(rightPanel.style.width).toBeGreaterThan('50%');
方案二:原生JS事件实现(非React场景)
// 1. 触发gutter的mousedown const mousedownEvent = new MouseEvent('mousedown', { clientX: gutter.getBoundingClientRect().left, bubbles: true, cancelable: true }); gutter.dispatchEvent(mousedownEvent); // 2. 触发document的mousemove(Split.js在此监听拖动) const mousemoveEvent = new MouseEvent('mousemove', { clientX: gutter.getBoundingClientRect().left - 200, bubbles: true, cancelable: true }); document.dispatchEvent(mousemoveEvent); // 3. 触发document的mouseup结束拖动 const mouseupEvent = new MouseEvent('mouseup', { bubbles: true, cancelable: true }); document.dispatchEvent(mouseupEvent); // 断言宽度变化 expect(parseInt(leftPanel.style.width)).toBeLessThan(50); expect(parseInt(rightPanel.style.width)).toBeGreaterThan(50);
3. 关键注意事项
- 必须触发document级别的事件:Split.js在gutter的mousedown事件后,会将mousemove/mouseup的监听绑定到document上,仅触发gutter的事件不会生效。
- 用act()包裹异步更新:React组件中拖动后的宽度更新是异步的,需用
act()确保DOM更新完成后再执行断言。 - mock坐标计算(可选):若jsdom环境中
getBoundingClientRect()返回值不准确,可手动mock:
jest.spyOn(gutter, 'getBoundingClientRect').mockReturnValue({ left: 500, top: 0, width: 10, height: 500, bottom: 500, right: 510 });
内容的提问来源于stack exchange,提问作者guziczek
相关产品推荐
相关产品推荐

