Jest测试中如何验证execCommand('copy')执行后的剪贴板实际内容
Jest 下验证 execCommand 复制内容的实现方案
你之前只对document.execCommand做返回值和参数的mock,确实无法校验实际复制的内容——Jest 跑测试用的jsdom环境本身没有实现真实的系统剪贴板交互,只要补全mock层的内容捕获逻辑,不需要访问真实剪贴板就能完成校验,具体实现如下:
核心实现思路
document.execCommand('copy')触发时,实际写入剪贴板的内容只有两个来源:
- 当前页面上被选中的普通文本/表单控件选中文本
- 业务代码在
copy事件回调里通过e.clipboardData.setData()手动写入的内容
你只需要在mock层拦截这两部分内容,就能准确拿到复制操作的实际写入值。
具体代码实现
1. 测试前置Mock配置
beforeEach(() => { let capturedCopyText = ''; // 绑定copy事件捕获逻辑 const copyHandler = (e) => { e.preventDefault(); const activeEl = document.activeElement; // 兼容input/textarea内选中文本的场景 if (activeEl instanceof HTMLInputElement || activeEl instanceof HTMLTextAreaElement) { capturedCopyText = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd); } // 兼容普通DOM节点选中文本的场景 else if (document.getSelection()) { capturedCopyText = document.getSelection().toString(); } // 兼容手动通过clipboardData写入内容的场景 if (e.clipboardData?.dataStore?.['text/plain']) { capturedCopyText = e.clipboardData.getData('text/plain'); } }; document.addEventListener('copy', copyHandler); // 重写execCommand的mock实现 jest.spyOn(document, 'execCommand').mockImplementation((command) => { if (command === 'copy') { // 构造符合规范的copy事件,挂载clipboardData对象 const copyEvent = new Event('copy', { bubbles: true, cancelable: true }); Object.defineProperty(copyEvent, 'clipboardData', { value: { dataStore: {}, setData(type, value) { this.dataStore[type] = value; }, getData(type) { return this.dataStore[type] || ''; } } }); document.dispatchEvent(copyEvent); // 把捕获到的文本挂在mock实例上,方便断言读取 document.execCommand.copiedText = capturedCopyText; return true; } return false; }); // 测试后清理环境 afterEach(() => { document.removeEventListener('copy', copyHandler); jest.restoreAllMocks(); }); });
2. 测试用例断言示例
import { render, fireEvent, screen } from '@testing-library/react'; import CopyButton from './CopyButton'; // 你的业务组件 test('点击复制按钮时,正确写入指定内容到剪贴板', () => { const testCopyText = '测试要复制的内容_123456'; render(<CopyButton text={testCopyText} />); // 触发复制操作 fireEvent.click(screen.getByText('复制')); // 原有参数校验保留 expect(document.execCommand).toHaveBeenCalledWith('copy'); // 直接断言捕获到的复制内容 expect(document.execCommand.copiedText).toBe(testCopyText); });
注意事项
- 不要尝试在单元测试里读取系统真实剪贴板,jsdom环境没有对应权限,也会导致测试在CI/无GUI环境跑失败
- 如果你的业务逻辑用了第三方封装的copy库(比如copy-to-clipboard),这套mock逻辑同样适用,因为这类库底层还是走的execCommand + 选中文本/clipboardData的逻辑
- 如果用例之间存在DOM污染,可以在jest配置里打开
testEnvironmentOptions: { url: 'http://localhost' },同时每个用例后重置document.body内容,避免选中文本串用例
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

