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

使用@jest/environment-jsdom-abstract模拟jsdom Location失败排查

处理Jest 30 + JSDOM 26中location.search模拟失败的问题

问题原因

  1. JSDOM 21+ 对Location对象的属性访问做了严格限制,直接修改location.search会触发底层导航逻辑,而Jest内置的JSDOM环境默认不支持跨文档导航,因此抛出Error: Not implemented: navigation to another Document错误。
  2. 你尝试通过@jest/environment-jsdom-abstract注入自定义Location实现,但Jest初始化时会优先加载内置的JSDOM环境,不会自动应用你的自定义实现,导致注入无效。

可行修改方案

方案1:用Jest Spy直接模拟getter/setter(推荐)

无需修改环境配置,直接在测试用例中对window.location.search的getter和setter做模拟,既能验证修改行为,又不会触发导航逻辑:

// 模拟search的初始值
jest.spyOn(window.location, 'search', 'get').mockReturnValue('?initial=val');

// 模拟setter,用于验证是否被修改
let mockSearchValue = '';
jest.spyOn(window.location, 'search', 'set').mockImplementation((val) => {
  mockSearchValue = val;
});

// 执行你的业务逻辑
yourFunctionThatModifiesSearch();

// 验证修改结果
expect(mockSearchValue).toBe('?updated=value');

方案2:全局禁用JSDOM导航检查

在jest.config.js中配置JSDOM,拦截导航请求并关闭相关错误:

module.exports = {
  testEnvironment: 'jsdom',
  testEnvironmentOptions: {
    jsdom: {
      url: 'http://localhost/',
      pretendToBeVisual: true,
      // 拦截导航请求,避免触发跨文档跳转报错
      onNavigation() {
        return Promise.resolve(null);
      }
    }
  }
};

方案3:自定义Jest环境注入Location实现

如果需要完全自定义Location的行为,可创建自定义Jest环境:

  1. 创建custom-jsdom-environment.js:
const JSDOMEnvironment = require('jest-environment-jsdom').default;

class CustomJSDOMEnv extends JSDOMEnvironment {
  constructor(config) {
    super(config);
    // 自定义Location类,覆盖search的get/set逻辑
    class CustomLocation extends this.global.Location {
      constructor() {
        super('http://localhost/');
        this._search = '';
      }
      get search() {
        return this._search;
      }
      set search(val) {
        this._search = val;
        // 可选:触发hashchange/popstate事件(如果业务依赖)
      }
    }
    // 替换全局Location类及window.location实例
    this.global.Location = CustomLocation;
    this.global.window.location = new CustomLocation();
  }
}

module.exports = CustomJSDOMEnv;
  1. 在jest.config.js中指定自定义环境:
module.exports = {
  testEnvironment: './custom-jsdom-environment.js'
};

注意事项

  • 不要直接赋值window.location.search或href,JSDOM 21+会触发真实导航逻辑导致报错;
  • 使用spy模拟时,必须明确指定'get'或'set'选项,因为location的属性是访问器属性而非普通属性。

内容的提问来源于stack exchange,提问作者htho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 06:12:43