如何在Jest环境下使用Puppeteer page测试任意ES6模块?
问题根因
ES6 模块的顶层作用域为独立的模块作用域,你通过 export default 导出的 MyFunction 默认不会挂载到浏览器全局 window 对象上,而 page.evaluate 执行的代码仅能访问浏览器全局作用域下的变量,因此直接调用会出现函数未定义的报错。
解决方案
方案1:修改原模块挂载到全局(实现成本最低)
在 MyModule.js 末尾追加代码,将导出的函数挂载到 window 全局:
// MyModule.js 原有逻辑 export default MyFunction; // 新增挂载逻辑 if (typeof window !== 'undefined') { window.MyFunction = MyFunction; }
调整 Puppeteer 执行逻辑,增加模块加载完成的等待判断:
await page.setContent(input); await page.addScriptTag({ path: 'path/to/function/MyModule.js', type: 'module', }); // 等待函数挂载到全局,避免模块未加载完成就调用 await page.waitForFunction(() => window.MyFunction); const actualFieldLabel = await page.evaluate(async (selector) => { const field = document.querySelector(selector); const result = await window.MyFunction(field); return result; }, selector); // 注意将selector作为参数传入evaluate expect(actualFieldLabel).toBe(output);
方案2:不修改原模块,在evaluate中动态导入
如果不需要改动原模块代码,可以直接在 page.evaluate 内通过动态导入语法加载ES模块,注意路径要匹配浏览器上下文可访问的地址:
await page.setContent(input); const actualFieldLabel = await page.evaluate(async (selector) => { // 动态导入模块,路径需为浏览器可正常解析的地址 const { default: MyFunction } = await import('/path/to/function/MyModule.js'); const field = document.querySelector(selector); const result = await MyFunction(field); return result; }, selector); expect(actualFieldLabel).toBe(output);
注意事项
- 原
MyModule.js存在语法错误:你写的const MyFunction => {为非法语法,需修正为const MyFunction = async () => {,如果内部包含异步逻辑需显式添加async关键字 - 依赖路径校验:你的
MyModule依赖MySubModule,需确保所有依赖的路径在浏览器上下文都能正常解析,否则会出现模块加载失败的问题 - 路径适配:如果使用动态导入方案,建议先启动本地静态服务,使用完整的http路径导入模块,避免相对路径解析错误
内容的提问来源于stack exchange,提问作者devinm
相关产品推荐
相关产品推荐

