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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:17:07