Jest测试浏览器专属TypeScript脚本时无法识别window.location等浏览器属性的解决方案咨询
Jest测试浏览器专属TypeScript脚本时无法识别window.location等浏览器属性的解决方案咨询
嘿,我太懂你这个困扰了——Jest默认是在Node.js环境里跑测试的,压根没有浏览器那套全局对象,所以找不到window.location这类属性太正常了。下面给你几个实用的解决办法,你可以根据自己的需求来选:
方法一:用Jest内置的jsdom模拟完整浏览器环境
Jest其实自带了jsdom这个工具,能帮你模拟出一个浏览器的DOM环境,这样window、document甚至location这些对象就都自动存在了,不用一个个去mock。
步骤很简单:
- 先安装jsdom的类型定义(因为你用的是TypeScript):
npm install --save-dev @types/jsdom
- 修改你的Jest配置文件(比如
jest.config.ts或者jest.config.js),把测试环境改成jsdom:
export default { testEnvironment: 'jsdom', // 其他你原本的配置,比如transform、moduleFileExtensions之类的... };
这样配置完,Jest跑测试的时候就会模拟浏览器环境,你的脚本里用到的浏览器全局对象就能被正常识别了。
方法二:单独Mock window.location(适合不需要完整浏览器环境的场景)
如果你的脚本只用到了window.location这几个属性,不想引入完整的jsdom,那直接在测试文件里手动mock就行,还能精准控制每个测试用例里的location值。
比如在测试文件里这么写:
// 先处理TypeScript的类型问题,扩展Window接口 declare global { interface Window { location: Partial<Location>; } } // 在每个测试前重置mock,避免测试间互相影响 beforeEach(() => { delete (window as any).location; // 模拟你需要的location属性和方法 window.location = { href: 'https://initial-url.com', reload: jest.fn(), assign: jest.fn(), // 脚本里用到啥就加啥 }; }); // 然后写你的测试用例 test('测试脚本中的跳转逻辑', () => { // 调用你脚本里的方法 yourBrowserScriptFunction(); // 验证location的变化是否符合预期 expect(window.location.assign).toHaveBeenCalledWith('https://target-page.com'); });
这里用Partial<Location>是因为我们不需要模拟Location接口的所有属性,只模拟用到的部分就行,TypeScript也不会报错。
方法三:全局配置Mock(适合多个测试文件都需要的场景)
如果你的很多测试文件都需要用到浏览器全局对象的mock,那可以把mock逻辑放到全局的setup文件里,不用每个测试文件都写一遍。
- 先创建一个
setup-jest.ts文件,写好全局mock的逻辑:
// setup-jest.ts beforeEach(() => { // 用jest.spyOn来mock window.location的getter jest.spyOn(window, 'location', 'get').mockReturnValue({ href: 'https://default-test-url.com', reload: jest.fn(), assign: jest.fn(), }); });
- 然后在Jest配置文件里引入这个setup文件:
export default { setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'], // 其他配置... };
这样所有测试文件在运行前都会执行这个setup里的逻辑,全局的window.location就被mock好了。
另外补充一句,如果你的脚本还用到了其他浏览器API(比如localStorage、navigator),用上面的方法同样能处理——要么用jsdom提供完整模拟,要么单独mock对应的属性就行。
备注:内容来源于stack exchange,提问作者programmer
相关产品推荐
相关产品推荐

