Puppeteer ESM导入时Locator.race报错问题排查与解决
Puppeteer ESM导入后
puppeteer.Locator.race报错的原因与解决方案 错误原因
Puppeteer的CommonJS和ESM导出结构存在差异:
- CommonJS模式下,
require('puppeteer')会返回包含所有API(包括Locator类)的完整对象,所以puppeteer.Locator能正常访问。 - ESM模式下,默认导出的
puppeteer仅包含核心API集合,Locator是独立的具名导出项,直接用import puppeteer from 'puppeteer-core'无法获取到Locator,导致puppeteer.Locator为undefined,调用.race时触发TypeError。
解决方案(最小修改录制脚本)
方案1:单独导入Locator类
只需新增一行导入语句,然后将脚本中puppeteer.Locator.race替换为Locator.race,其余录制代码完全保留:
// const puppeteer = require('puppeteer'); // 原CommonJS导入 import puppeteer from 'puppeteer-core'; import { Locator } from 'puppeteer-core'; // 新增具名导入 (async () => { // ... 原录制脚本内容不变 { const targetPage = page; await Locator.race([ // 仅修改此处的调用前缀 targetPage.locator('app-header li:nth-of-type(1) > a'), targetPage.locator('::-p-xpath(/html/body/app-root/app-layout/app-header/nav/div/div/ul/li[1]/a)'), targetPage.locator(':scope >>> app-header li:nth-of-type(1) > a'), targetPage.locator('::-p-aria( Override User)'), targetPage.locator('::-p-text(Override User)') ]) .setTimeout(timeout) .click({ offset: { x: 68.199951171875, y: 11.625, }, }); } // ... 后续脚本内容不变 })();
方案2:使用命名空间导入(无需修改录制脚本)
将ESM导入方式改为命名空间导入,一次性获取Puppeteer的所有导出项,这样原脚本中的puppeteer.Locator.race可以完全保留,无需任何修改:
// const puppeteer = require('puppeteer'); // 原CommonJS导入 import * as puppeteer from 'puppeteer-core'; // 改为命名空间导入 (async () => { // 所有录制脚本内容完全不变,包括 puppeteer.Locator.race 的调用 })();
这两种方案都不需要大幅改写录制脚本,完美适配Mocha测试环境,同时保留了Chrome录制器生成的Locator.race逻辑,避免了用Promise.race替代的繁琐修改。
内容的提问来源于stack exchange,提问作者Fritz Herbers
相关产品推荐
相关产品推荐

