Skip to main content
Cypress应用

Node事件概述

Node事件钩子使您能够接入、修改或扩展Cypress的内部行为。

通常情况下,作为用户,您的所有测试代码、应用程序和Cypress命令都在浏览器中执行。但Cypress也是一个Node进程,可用于改变Cypress的行为或暴露插件供他人使用。

setupNodeEvents 使您能够接入运行在浏览器外部的Node进程。

Node事件钩子是您编写自定义代码的"接缝",这些代码在Cypress生命周期的特定阶段执行。

setupNodeEvents

setupNodeEvents函数接收2个参数:onconfig。它可以返回一个同步值,也可以返回一个Promise,该Promise将被等待直到解析完成。这使您能够执行异步操作,例如从文件系统读取文件。

如果您返回或解析一个对象,Cypress会将该对象合并到config中,从而使您能够覆盖配置或环境变量。

const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
// 在此配置插件
},
},
})

on

on是一个函数,用于注册监听Cypress暴露的各种事件

注册监听事件如下所示:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
on('<event>', (arg1, arg2) => {
// 插件代码在此
})
},
},
})

事件列表

每个事件都记录了自己的参数签名。

事件描述
after:run运行结束后触发。
after:screenshot截图完成后触发。
after:spec单个spec运行完成后触发。
before:browser:launch浏览器启动前立即触发。
before:run运行开始前触发。
before:spec当spec即将运行时触发。
file:preprocessor当spec或相关文件需要为浏览器转译时触发。
taskcy.task命令结合使用。

config

config是已解析的Cypress配置对象,用于打开的项目。

此配置包含所有传递给浏览器的项目值。

一些插件可能会利用或需要这些值,以便根据配置采取特定操作。如果这些值被编程修改,Cypress将使用新值。

caution

config对象还包括以下不属于标准配置的额外值。这些值是只读的,无法从插件文件中修改。

  • configFile: Cypress配置文件的绝对路径。有关此值的更多信息,请参阅--config-fileconfigFile文档。
  • projectRoot: 项目根目录的绝对路径(例如/Users/me/dev/my-project
  • version: Cypress的版本号。可用于处理重大变更。

请在此查看我们的API文档以了解如何修改配置。

使用场景

配置

接入node事件允许您以编程方式更改来自Cypress配置文件cypress.env.json命令行或系统环境变量的已解析配置和环境变量。

这使您能够:

  • 使用具有各自配置的多个环境
  • 根据环境交换环境变量
  • 使用内置的fs库读取配置文件
  • 更改用于测试的浏览器列表
  • yml编写配置

查看我们的配置API文档,了解如何使用此事件。

预处理器

file:preprocessor事件用于自定义测试代码如何被转译并发送到浏览器。默认情况下,Cypress处理ES2015+、TypeScript和CoffeeScript,使用webpack打包到浏览器。

您可以使用file:preprocessor事件来:

  • 添加最新的ES*支持
  • 用ClojureScript编写测试代码
  • 自定义Babel设置以添加自己的插件
  • 自定义TypeScript编译选项
  • 用Vite或其他工具替换Webpack

查看我们的文件预处理器API文档,了解如何使用此事件。

运行生命周期

before:runafter:run事件分别在运行前后触发。

您可以使用before:run来:

  • 设置运行报告
  • 启动计时器以计算运行时间

您可以使用after:run来:

  • 完成在before:run中设置的运行报告
  • 停止在before:run中设置的计时器

Spec生命周期

before:specafter:spec事件分别在单个spec运行前后触发。

您可以使用before:spec来:

  • 设置spec运行报告
  • 启动计时器以计算spec运行时间

您可以使用after:spec来:

  • 完成在before:spec中设置的报告
  • 停止在before:spec中设置的计时器
  • 删除为spec录制的视频。这可以避免花费时间和计算资源压缩和上传视频。您可以根据spec的结果有条件地执行此操作,例如如果它通过(因此保留失败测试的视频用于调试目的)。

查看Before Spec API文档After Spec API文档,了解如何使用这些事件。

浏览器启动

before:browser:launch事件可用于修改每个特定浏览器的启动参数。

您可以使用before:browser:launch事件来:

  • 加载Chrome扩展
  • 启用或禁用实验性Chrome功能
  • 控制加载哪些Chrome组件

查看我们的浏览器启动API文档,了解如何使用此事件。

截图处理

after:screenshot事件在截图保存到磁盘后调用。

您可以使用after:screenshot事件来:

  • 保存有关截图的详细信息
  • 重命名截图
  • 通过调整大小或裁剪来操作截图图像

查看我们的After Screenshot API文档,了解如何使用此事件。

cy.task

task事件与cy.task()命令结合使用。它允许您在Node中编写任意代码,以完成浏览器中无法完成的任务。

您可以使用task事件来:

  • 操作数据库(种子、读取、写入等)
  • 在Node中存储您希望持久化的状态(因为驱动程序在访问时会完全刷新)
  • 执行并行任务(如在Cypress之外发出多个http请求)
  • 运行外部进程(如启动另一个浏览器如Safari或puppeteer的Webdriver实例)

执行上下文

setupNodeEvents函数在Cypress打开项目时调用。

Cypress通过生成一个独立的child_process来实现这一点,该进程然后requireCypress配置文件。这与Visual Studio Code或Atom的工作方式类似。

此代码将使用启动Cypress的Node版本执行。

npm模块

当Cypress执行setupNodeEvents函数时,process.cwd()将设置为您的项目路径。此外,您将能够require任何已安装的node模块,包括项目中的本地文件。

例如,如果您的package.json如下所示:

{
"name": "My Project",
"dependencies": {
"debug": "x.x.x"
},
"devDependencies": {
"lodash": "x.x.x"
}
}

那么您可以在setupNodeEvents函数中执行以下任何操作:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
const _ = require('lodash') // 是的,dev依赖
const path = require('path') // 是的,核心node库
const debug = require('debug') // 是的,依赖
const User = require('./lib/models/user') // 是的,相对本地模块

console.log(__dirname) // /Users/janelane/Dev/my-project
console.log(process.cwd()) // /Users/janelane/Dev/my-project
},
},
})

错误处理

Cypress配置文件在自己的子进程中加载,因此与Cypress本身运行的上下文隔离。这意味着您无法意外修改或更改Cypress自身的执行方式。

如果您的setupNodeEvents函数有未捕获的异常、Promise的未处理拒绝或语法错误,Cypress会自动捕获这些错误并在控制台甚至Cypress本身中显示给您。

setupNodeEvents函数中的错误_不会崩溃_Cypress。

文件更改

通常在Node中编写代码时,更改任何文件后通常需要重新启动进程。

Cypress自动监视您的Cypress配置文件,任何更改都会立即生效。我们将读取文件并再次执行导出的函数。

这使您即使在Cypress已经运行时也能迭代插件代码。

真实世界示例

真实世界应用(RWA) 使用任务重新种子数据库,并为各种测试场景过滤/查找测试数据。

caution

⚠️ 这段代码属于 setupNodeEvents 函数的一部分, 因此会在 Node 环境中执行。你不能在此函数中调用 Cypresscy 命令, 但可以直接访问文件系统和操作系统的其他部分。

const { defineConfig } = require('cypress')

module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
on('task', {
async 'db:seed'() {
// 用测试数据种子数据库
const { data } = await axios.post(`${testDataApiEndpoint}/seed`)
return data
},

// 从数据库(MySQL、PostgreSQL等)获取测试数据
'filter:database'(queryPayload) {
return queryDatabase(queryPayload, (data, attrs) =>
_.filter(data.results, attrs)
)
},
'find:database'(queryPayload) {
return queryDatabase(queryPayload, (data, attrs) =>
_.find(data.results, attrs)
)
},
})
},
},
})

查看Real World App测试套件,了解这些任务的实际应用。