@cypress/puppeteer

中文文档
1.0.0发布于 2026/11/13MITTypeScriptCommonJS近 30 天下载 3.1万

用 Puppeteer 增强 Cypress 测试的插件

中文使用文档
文档目录31 节
  1. 目录
  2. 安装
  3. 类型脚本
  4. 升级到1.0
  5. 这影响我吗?
  6. 接下来怎么办
  7. 兼容性
  8. 如何运作
  9. 检索
  10. 超时
  11. 使用量
  12. 1. 在您的 Cypress 配置中注册信件处理器
  13. 2. 导入支持文件
  14. 3. 电话 cy.puppeteer() 在您的光谱中
  15. API 密码
  16. setup(options)
  17. retry(functionToRetry[, options])
  18. cy.puppeteer(messageName[, ...args])
  19. 实例
  20. 切换到新标签
  21. 创建新标签
  22. 解决问题
  23. @cypress/puppeteer does not work in Google Chrome v137 and …
  24. Cannot communicate with the Cypress Chrome extension. Ensur…
  25. Lost the reference to the browser
  26. cy.task('__cypressPuppeteer__') timed out after waiting 600…
  27. Protocol error (Target.createTarget): Not supported
  28. Only browsers in the "Chromium" family are supported
  29. Could not find message handler with the name ...
  30. 捐款
  31. 更改日志

@ cypress/ puppeteer (简体中文)

使用 Puppeteer 的浏览器 API 从你的Cypress测试 只有一个命令.

Cypress用一分页运行您的测试,所以它不能切换到您的应用程序打开的分页或窗口,或者一次与多页一起工作. 此插件会给您一个 Puppeteer Browser 连接到启动的浏览器 Cypress. 你和Puppeteer合作 然后把结果传回你的判断.

对于Cypress自己能做的任何事情,使用Cypress命令取而代之. 它们自动重试并在命令日志中显示每个步骤,同时 cy.puppeteer() 不重试并记录整个处理器的单个条目.

目录

安装

以 npm 为单位 :

npm install --save-dev @cypress/puppeteer

用纱线:

yarn add --dev @cypress/puppeteer

类型脚本

要获得类型 cy.puppeteer(),将支持类型添加到您的 tsconfig.json数字 :

{
  "compilerOptions": {
    "types": ["cypress", "@cypress/puppeteer/support"]
  }
}

这个 setup 财务报告和审定财务报表 retry 函数带有它们自己的类型定义,因此不需要为您的 Cypress 配置文件添加配置.

升级到1.0

1.0 版本升级捆绑 puppeteer-core 从v21到v24,需要Cypress 14.0.0或后期. 插件自己的API没有改变 : setup, (中文(简体) ), retry,以及 cy.puppeteer() 一样的工作方式。 不过,你的信息处理者会收到一个Pippeteer Browser 直接,所以Puppeteer在v21和v24之间打破了变化,可以影响它们内部的代码.

我们做了这个升级,所以插件保持与当前Chrome发行的兼容性,并取出Puppeteer更可靠的连接处理. Puppeteer v24需要Node.js 18或后期,这就是为什么仍然支持Node.js 16的Cypress 13不再被支持的原因.

这影响我吗?

如果其中任何一个都是真的,它就会影响你:

  • 你用Cypress 13号. 升级为 Cypress 14.0.0 或 后先.
  • 您的邮件处理器使用一个改变的 Puppeteer API .

这些是Puppeteer最有可能出现在处理器中的改变:

傀儡侠v21傀儡侠 v24
page.waitForTimeout(ms)已删除。 等待一个特定的条件与 page.waitForSelector() 或者说 page.waitForFunction(),或使用 new Promise((resolve) => setTimeout(resolve, ms))。 。 。 .
page.$x(expression) 财务报告和审定财务报表 page.waitForXPath(expression)已删除。 使用 ::-p-xpath() 例如,选择器 page.$$('::-p-xpath(//h2)') 或者说 page.waitForSelector('::-p-xpath(//h2)')。 。 。 .
browser.createIncognitoBrowserContext()重命名为 browser.createBrowserContext()。 。 。 .
puppeteer.devices已删除。 导入 KnownDevices 从 puppeteer-core 换句话说.
addEventListener() 财务报告和审定财务报表 removeEventListener() 在傀儡对象上已删除。 使用 on() 财务报告和审定财务报表 off()。 。 。 .
屏幕截图和 PDF 方法被输入为返回节点.js Buffer他们被打成返回a Uint8Array在类型脚本中,将结果包入 Buffer.from() 如果你需要的话 Buffer 方法。 。 .
HTTPRequest.url() 财务报告和审定财务报表 HTTPResponse.url() 留下 URL 碎片它们包括碎片,例如: #section。 。 。 .

完整的列表请参见第22.0.0、23.0.0和24.0.0版的分页更改 傀儡核心变化日志。 。 。 .

接下来怎么办

  1. 如果你在Cypress 13上,升级到Cypress 14.0.
  2. 搜索上表中的 API 处理器并更新它们 .
  3. 如果你通过自己的Pippeter模块 puppeteer 选项升级到v24.
  4. 运行您调用的规格 cy.puppeteer()。 。 。 .

如果你还不能做出这些修改,请继续前次发布 npm install --save-dev @cypress/puppeteer@0 直到你准备好了.

兼容性

  • Cypress 14.0.0 或晚点.
  • 节点.js 18或以后 用于装入 Cypress 配置的进程,每个节点.js版本 Cypress 14 支持的配置已经满足。 捆绑起来 puppeteer-core v24需要这个.
  • 仅Chromium-family浏览器. 通话 cy.puppeteer() 在 Firefox 或 WebKit 中以出错失败.

哪些工作取决于浏览器以及它是否运行无头(cypress run)或标题(cypress open 或者说 cypress run --headed:

浏览器无头标题打开新标签 browser.newPage()
电子对对没有
用于测试的铬对对对
Google Chrome 136 及更早时对对对
Google Chrome 137 以及后来对没有是的,只有无头
基于铬的其他浏览器, 如 Edge对只有在浏览器可以装入 Cypress 扩展名时对
火狐, WebKit 软件没有没有没有

Electron无法从 Puppeteer 打开新的标签或窗口. 电子不支持通过 Chrome DevTools 协议创建页面,所以 browser.newPage() 失败 Protocol error (Target.createTarget): Not supported。使用您的应用程序打开的标签和窗口工作,例如 切换到新标签在电子公司工作.

Google Chrome 137 和 后来无法运行 由 :. 在标题为 Chromium 浏览器中,插件需要 Cypress 扩展名(见 如何运作)和Chrome 137 移除了该设备 --load-extension 装入它的旗帜。 当插件检测到这个组合时,它会向浏览器的启动扔出一个错误. 对于头跑,使用Electron,Chrome来测试,或者Chromium代替. Cypress Docker 图像存储器有实例 测试颜色 财务报告和审定财务报表 铬。 。 。 .

如何运作

插件有两个半部分:

  • 在您的 Cypress 配置中,您将命名的邮件处理器注册到 setup()。这些处理器运行在Node.js,而不是在浏览器中.
  • 在你的光谱中,你打电话 cy.puppeteer('handlerName', ...args) 运行其中之一。 在引擎盖下,这是 cy.task(),因此它遵循同样的参数规则、返回值和超时.

每次都这样 cy.puppeteer() 运行,插件 :

  1. 将Puppeteer连接到Cypress推出的浏览器.
  2. 给那个小便便师打电话 Browser 以及你通过的任何论据.
  3. 在Electron以外的标题Chrimium浏览器中,通过Cypress扩展带回了主Cypress分页到前方,因此在与其他分页合作后,你的测试可以继续运行.
  4. 从浏览器中断开 Puppeteer. 浏览器本身保持开放 .
  5. 使用您的操作器返回 Cypress 命令链的值 .

因为每通电话都是新鲜的,最后就关闭了,所以不要坚持 Browser, (中文(简体) ), Page,或元素参考 cy.puppeteer() 打电话 在每个操作员内部再找一次.

检索

cy.puppeteer() 运行你的处理器一次。 如果一项主张在失败后连锁起来,例如: .should('include', '/new-page')Cypress不会再运行操作器了 当一个处理器依赖于需要时间出现的东西, 就像一个仍然打开的标签, 等待它在处理器内部 retry 或一种Puppeteer方法,例如: page.waitForSelector()。 。 。 .

超时

每个 cy.puppeteer() 呼叫受 Cypress 的限制 taskTimeout 设置,默认为6万毫秒. cy.puppeteer() 不采取自己的超时选择, 所以给一个慢处理器更多的时间,提高 taskTimeout 在您的 Cypress 配置中或用于单个测试 :

it('waits for a slow tab', { taskTimeout: 120000 }, () => {
  cy.puppeteer('waitForSlowTab')
})

使用量

1. 在您的 Cypress 配置中注册信件处理器

// cypress.config.ts
import { defineConfig } from 'cypress'
import { setup, retry } from '@cypress/puppeteer'

export default defineConfig({
  e2e: {
    setupNodeEvents (on) {
      setup({
        on,
        onMessage: {
          async getNewTabTitle (browser, urlFragment) {
            // cy.puppeteer() doesn't retry, so wait here until the tab has opened
            const page = await retry(async () => {
              const pages = await browser.pages()
              const page = pages.find((page) => page.url().includes(urlFragment))

              if (!page) throw new Error(`No tab with a URL containing ${urlFragment} yet`)

              return page
            })

            // Whatever you return is yielded by cy.puppeteer() in your spec
            return page.title()
          },
        },
      })
    },
  },
})

2. 导入支持文件

// cypress/support/e2e.ts
import '@cypress/puppeteer/support'

3. 电话 cy.puppeteer() 在您的光谱中

// cypress/e2e/spec.cy.ts
it('opens a new tab', () => {
  cy.visit('/')
  cy.get('button').click() // opens a new tab

  cy.puppeteer('getNewTabTitle', '/new-page').should('equal', 'New page')
})

API 密码

setup(options)

把这个叫进去 setupNodeEvents 以注册您的邮件处理器.

import { setup } from '@cypress/puppeteer'

setup({ on, onMessage, puppeteer })

选项

选项需求说明
on对这个 on 事件注册函数 setupNodeEvents 接收.
onMessage对一个按键为消息名且其值为处理器函数的对象。 见 信件处理器。 。 。 .
puppeteer没有一个Puppeteer模块(来自 puppeteer 或者说 puppeteer-core用于代替 puppeteer-core 与此插件捆绑 。 安装符合此插件的版本 puppeteer-core 依赖性,所以您的软件包管理器在您的工程和插件之间共享一个副本 。 在TypeScript中,一个来自不同副本的模块无法进行打字检查,甚至在同一大版本内也是如此.

setup 如果 options, (中文(简体) ), on,或 onMessage 缺少,或者 onMessage 不是一个普通对象.

信件处理器

每个键入 onMessage 是您可以传递给 cy.puppeteer(). 它的功能运行于Node.js,因此Cypress命令和DOM API在其内部不可用——取而代之的是Puppeteer API.

处理者收到:

  • browser: 一个傀儡 Browser 实例连接到 Cypress 启动的浏览器.
  • ...args: 任何移交给 cy.puppeteer() 在消息名称后.

处理器可以是同步的或 async. 他们返回(或决心返回)的东西由 cy.puppeteer()数字 :

  • 返回值必须是可序列的, 就像 cy.task() 结果.
  • 正在返回 undefined 产量 null,从 cy.task() 不允许 undefined。 。 。 .
  • 如果处理者扔或拒绝, cy.puppeteer() 以错误消息失败测试 .

retry(functionToRetry[, options])

您的邮件处理器的助手, 它会不停地调用一个函数直到它成功 。 对于需要一点时间出现的东西来说是有用的,就像一个仍在打开的分页.

import { retry } from '@cypress/puppeteer'

const page = await retry(async () => {
  const pages = await browser.pages()
  const page = pages.find((page) => page.url().includes('page-2.html'))

  if (!page) throw new Error('Could not find page')

  return page
})

functionToRetry

要求. 函数(同步或 async打电话。 如果它扔或拒绝, retry 等待和唤起它。 一旦它成功,我们就会, retry 以返回值解决.

options

可选的.

选项默认说明
timeout4000多久再试一次,以毫秒计。 一旦到达, retry 拒绝方式 Failed retrying after <timeout>ms: <last error message>。 。 。 .
delayBetweenTries200要等多久 尝试之间,以毫秒计.

超时被计算为两次尝试之间的延迟,所以在里面花的时间 functionToRetry 它本身没有被包含在内。 一个缓慢的函数可以使 retry 运行时间大于 timeout。 。 。 .

cy.puppeteer(messageName[, ...args])

运行已注册的邮件处理器 messageName 并产生回报值.

cy.puppeteer('testNewTab', 'value 1', 42, [true, false])

messageName

要求. 匹配其中一个密钥的字符串 onMessage 您通过选项 setup。如果没有匹配,则命令失败并列出注册名称.

...args

可选的. 传递给信件处理器的值 。 它们从浏览器被发送到Node.js,所以它们必须是可序列的.

例如,上面的呼叫像这样到达处理器中:

setup({
  on,
  onMessage: {
    testNewTab (browser, stringArg, numberArg, arrayOfBooleans) {
      // stringArg === 'value 1'
      // numberArg === 42
      // arrayOfBooleans[0] === true, arrayOfBooleans[1] === false
    },
  },
})

实例

这两个例子都存在于这个软件包中 循环测试 财务报告和审定财务报表 cypress.config.ts (英语)在那里你可以运行他们自己。 这个配置还启动一个小型静态服务器 http://localhost:8000 并设定为 baseUrl,所以下面的URL指向这里.

示例使用标签,但同一方法对窗口有效. " 傀儡 " 将两者都视为 Page 类。 。 。 .

切换到新标签

这个例子说明如何:

  • 查找 Cypress 测试中打开的动作标签
  • 等那个标签 retry
  • 用 Puppeteer 从标签中读取内容
  • 把这个内容传回Cypress 供他断言

cypress/e2e/多塔布.cy.ts

it('switches to a new tab', () => {
  cy.visit('/cypress/fixtures/page-1.html')
  cy.get('input').type('Hello from Page 1')
  cy.get('button').click() // Triggers a new tab to open

  cy
  .puppeteer('switchToTabAndGetContent')
  .should('equal', 'You said: Hello from Page 1')
})

cypress.config.ts (英语)

import { defineConfig } from 'cypress'
import type { Browser as PuppeteerBrowser, Page } from 'puppeteer-core'
import { setup, retry } from '@cypress/puppeteer'

export default defineConfig({
  e2e: {
    setupNodeEvents (on) {
      setup({
        on,
        onMessage: {
          async switchToTabAndGetContent (browser: PuppeteerBrowser) {
            // The new tab may not have opened and loaded yet, so keep looking until it has
            const page = await retry<Promise<Page>>(async () => {
              // The browser will eventually have 2 tabs open: the Cypress tab and the new tab.
              // In Puppeteer, tabs and windows are called pages.
              const pages = await browser.pages()
              const page = pages.find((page) => page.url().includes('page-2.html'))

              // Throwing tells `retry` to try again
              if (!page) throw new Error('Could not find page')

              // Returning resolves `retry` with the page
              return page
            })

            // Cypress keeps focus on its own tab, so bring the new page to the front before interacting with it
            await page.bringToFront()

            const paragraph = (await page.waitForSelector('p'))!
            const paragraphText = await page.evaluate((el) => el.textContent, paragraph)

            // Clean up references before finishing
            paragraph.dispose()

            await page.close()

            // This value is yielded by cy.puppeteer() in the spec
            return paragraphText
          },
        },
      })
    },
  },
})

创建新标签

这个例子在"Electron"中行不通,因为"Electron"无法从"Puppeteer"打开新的分页. 运行在Chrome测试,Chromium,或Edge。 见 兼容性 详细情况.

这个例子说明如何:

  • 传递参数从 cy.puppeteer() 给信件处理器
  • 打开新标签并访问 Pippeteer 的页面
  • 将内容从该分页传回 Cypress 进行断言

cypress/e2e/多塔布.cy.ts

it('creates a new tab', () => {
  cy.visit('/cypress/fixtures/page-3.html')
  // Read a value from the page and pass it through to the message handler
  cy.get('#message').invoke('text').then((message) => {
    cy
    .puppeteer('createTabAndGetContent', message)
    .should('equal', 'I approve this message: Cypress and Puppeteer make a great combo')
  })
})

cypress.config.ts (英语)

import { defineConfig } from 'cypress'
import type { Browser as PuppeteerBrowser } from 'puppeteer-core'
import { setup } from '@cypress/puppeteer'

export default defineConfig({
  e2e: {
    setupNodeEvents (on) {
      setup({
        on,
        onMessage: {
          async createTabAndGetContent (browser: PuppeteerBrowser, text: string) {
            // Opens a new tab in the Cypress-launched browser
            const page = await browser.newPage()

            // `text` comes from the cy.puppeteer() call in the spec
            await page.goto(`http://localhost:8000/cypress/fixtures/page-4.html?text=${encodeURIComponent(text)}`)

            const paragraph = (await page.waitForSelector('p'))!
            const paragraphText = await page.evaluate((el) => el.textContent, paragraph)

            // Clean up references before finishing
            paragraph.dispose()

            await page.close()

            // This value is yielded by cy.puppeteer() in the spec
            return paragraphText
          },
        },
      })
    },
  },
})

解决问题

@cypress/puppeteer does not work in Google Chrome v137 and higher in cypress open mode (or headed run mode)

Chrome 137从命令行中移除了加载扩展的支持,插件需要在标题模式下Cypress扩展. 切换到Electron,Chrome用于测试,或者Chrome用于头部运行,或者无头运行Chrome cypress run。见 兼容性 详细情况.

Cannot communicate with the Cypress Chrome extension. Ensure the extension is enabled when using the Puppeteer plugin.

每个处理器在标题为Chrimium的浏览器中运行后,插件会要求Cypress扩展将主Cypress分页带回前方. 这个错误意味着扩展在2秒内没有响应. 一些事情需要检查:

  • 如果使用Google Chrome 137或后期,则切换到Chrome进行测试或铬. 见下载指令。 。 。 .
  • 确保访问启动的浏览器 Cypress 中启用 Cypress 扩展 chrome://extensions/。 。 。 .
  • 确保你的公司的安保政策允许Cypress扩展. 它的身份证是 caljajdfkjjjdehjdoimjkkakekklcck。 。 。 .

Lost the reference to the browser

这通常发生在您的 Cypress 配置重装时, 但浏览器不会重新启动 。 关闭浏览器并从Cypress再次打开.

cy.task('__cypressPuppeteer__') timed out after waiting 60000ms

一个信息处理器比Cypress要长 taskTimeout。检查处理器是否在等待永不发生的事情,例如一个与URL不匹配的标签. 如果处理者只是慢,就提高 taskTimeout。见 超时。 。 。 .

Protocol error (Target.createTarget): Not supported

您的邮件处理器呼叫 browser.newPage() 在Electron中运行时,它无法从Puppeteer中打开新的标签或窗口. 运行 Chrome 中的光谱用于测试, Chromium, 或者 Edge 代替 。 您的应用程序打开的标签和窗口仍然在Electron工作.

Only browsers in the "Chromium" family are supported

你在Firefox或WebKit里跑步 切换到一个Chromium-family浏览器,如Electron,Chrome用于测试,Chromium,或Edge.

Could not find message handler with the name ...

名字传到 cy.puppeteer() 不匹配任何密钥在 onMessage。错误列出了已注册的名称,所以通常是快速打字修复.

捐款

这个包裹住在 单相压运行 yarn 首先从寄存器根中运行这些命令 npm/puppeteer。 。 。 .

将类型脚本文件建入 dist/数字 :

yarn build

文件更改时重建 :

yarn watch

在不排放文件的情况下检查类型( E)yarn build 在类型出错时不会失败, 因此在打开 PR 之前运行 :

yarn check-ts

林特:

yarn lint

运行单位测试一次:

yarn test

以监视模式运行单元测试 :

yarn test-watch

打开 Cypress 测试 :

yarn cypress:open

在Chrome进行一次Cypress测试:

yarn cypress:run

更改日志

版本与发布记录

@cypress/puppeteer 共发布 14 个版本,首次发布于 2023/11/29;过去 12 个月发布了 5 个版本。

版本发布日期距今
1.0.0latest2026/11/13今天
0.0.0-dev.876162026/11/0310 天前
0.0.0-dev.876132026/11/0310 天前
0.1.102026/10/011 个月前
0.1.92026/09/251 个月前
0.1.82025/10/041.1 年前

关于 @cypress/puppeteer 的常见问题

@cypress/puppeteer 是什么?

用 Puppeteer 增强 Cypress 测试的插件

如何安装 @cypress/puppeteer?

在项目目录运行 npm install @cypress/puppeteer,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:cypress(>=14.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cypress/puppeteer 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cypress/puppeteer 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@cypress/puppeteer 可以商用吗?

@cypress/puppeteer 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cypress/puppeteer 的下载量有多少?

根据 npm 官方下载统计,@cypress/puppeteer 在 2026/10/11 – 2026/11/09 这 30 天内被下载 30,608 次,日均约 1,020 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cypress/puppeteer 还在维护吗?

最新版本 1.0.0 发布于 2026/11/13(今天);至今共发布 14 个版本,其中过去 12 个月发布了 5 个;首次发布于 2023/11/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。