Vue3测试ref的focus()方法失败,为何activeElement断言不匹配?
问题原因与解决方案
你的测试失败是因为默认的JSDOM测试环境(Vue测试工具默认使用的无头浏览器环境)处于非视觉模拟模式,调用focus()方法不会实际更新document.activeElement,所以即使组件正确执行了focus(),测试里拿到的activeElement还是<body>。
下面提供两种可行的解决方法:
方法1:配置测试环境支持焦点状态
修改测试框架的配置,让JSDOM开启视觉模拟模式,这样focus()会正确更新document.activeElement。
针对Vitest(vitest.config.js)
export default defineConfig({ test: { environmentOptions: { jsdom: { pretendToBeVisual: true } } } })
针对Jest(jest.config.js)
module.exports = { testEnvironmentOptions: { jsdom: { pretendToBeVisual: true } } }
配置完成后,你原来的测试代码就能正常通过了。
方法2:模拟focus方法并断言调用(无需修改环境配置)
如果不想调整环境配置,可以直接mockHTMLElement.prototype.focus,验证组件是否正确调用了该方法——这其实更聚焦于组件的行为逻辑(是否执行了聚焦操作),而非依赖环境状态:
describe('App', () => { it('should auto focus input element', async () => { // 监听focus方法并mock实现 const focusSpy = vi.spyOn(HTMLElement.prototype, 'focus').mockImplementation(() => {}); const wrapper = mount(App); const inputElement = wrapper.find('input'); expect(inputElement.exists()).toBeTruthy(); await nextTick(); // 断言focus方法被调用了一次 expect(focusSpy).toHaveBeenCalledTimes(1); // 进一步验证是目标input调用的focus expect(focusSpy).toHaveBeenCalledOn(inputElement.element); // 清理mock,避免影响其他测试 focusSpy.mockRestore(); }); });
注:如果使用Jest,将
vi.spyOn替换为jest.spyOn即可。
内容的提问来源于stack exchange,提问作者Gideon Oduro
相关产品推荐
相关产品推荐

