在Cypress中何时使用自定义命令与任务?

在Cypress中何时使用自定义命令与任务?,cypress,Cypress,自定义命令和任务之间有什么区别?我正在努力理解如何使用它们 自定义命令文档: 任务文档:一个命令(全局cy对象上的大多数方法)是一个函数,用于将操作排队(推送)到当前正在执行的命令队列中。队列以串行和异步方式执行(这就是为什么命令的返回值是一个具有.then方法的对象——但尽管如此,而且它的行为类似于promise,它仍然是一个对象)。在上一个命令完成之前,下一个命令不会执行 命令直接在浏览器中定义和执行 A是一个常规命令,但由您定义,而不是由Cypress定义的默认命令。自定义命令对于自动化您

自定义命令和任务之间有什么区别?我正在努力理解如何使用它们

自定义命令文档:


任务文档:

一个命令(全局
cy
对象上的大多数方法)是一个函数,用于将操作排队(推送)到当前正在执行的命令队列中。队列以串行和异步方式执行(这就是为什么命令的返回值是一个具有
.then
方法的对象——但尽管如此,而且它的行为类似于promise,它仍然是一个对象)。在上一个命令完成之前,下一个命令不会执行

命令直接在浏览器中定义和执行

A是一个常规命令,但由您定义,而不是由Cypress定义的默认命令。自定义命令对于自动化您在测试中反复重复的工作流非常有用(例如,通过将多个默认
cy
命令分组在一起)

命令用于与您的被测web应用程序(AUT)交互——最显著的是与DOM交互(例如,通过
cy.get(选择器)
查询DOM),并进行断言

同样重要的是要认识到,当命令以串行方式执行时,它们会立即排队(在同一个事件循环中),传递给它们的任何表达式都会随之计算。这不是特定于Cypress的行为,只是简单的JavaScript。这就是为什么你不能做这样的事情:

//用法不正确
让价值;
cy.get('.myInput')。invoke('val')。然后(val=>value=val);
cy.get('.mySecondInput')。类型(值);//✗ 此处未定义值
您也不能使用:

//用法不正确
让价值;
// ✗ 不适用于Cypress命令
const value=wait cy.get('.myInput').invoke('val');
cy.get('.mySecondInput').type(值);

任务是在Cypress后端进程(Node.js)上定义和执行的函数,而不是在浏览器中

要执行任务(您以前在
cypress/plugins/index.js
文件中定义了该任务),您需要首先将其作为测试中的常规命令排队。Cypress然后(当命令轮到执行时)向执行任务的后端进程发送消息

任务返回的数据被序列化(通过
JSON.stringify
或类似的方式),并发送回浏览器,在那里它被传递到一个回调,您可以使用
链接到
cy.task()
命令。然后(回调)

任务主要用于与您自己的服务器后端通信,例如为数据库种子;或用于I/O,例如读取/写入文件(尽管cypress提供了用于这些操作的命令,例如或)

没有默认任务——您执行的每个任务都需要首先定义自己


另一个要点是,在进程(Cypress浏览器进程和Cypress节点进程)之间发送的消息是通过发送的,并且必须是可序列化的。这意味着您传递给
cy.task(taskName,data)
的数据以及任务本身返回的响应都是字符串化的。因此,发送例如包含方法的对象将不起作用(也就是说,该方法根本不会被传输)。

Cypress命令通常不会返回承诺。文档将它们称为“thenable”,它只是意味着结果只能通过.then(result=>{})构造获得

这就是为什么上面的评论是正确的。(此处显示以供参考)

//用法不正确
让价值;
// ✗ 不适用于Cypress命令
const value=wait cy.get('.myInput').invoke('val');
cy.get('.mySecondInput').type(值);
但是,有一种本机方式包装cypress命令以获得真正的异步/等待行为,如下所示:

函数getAsync(查询,cb){ 让prom=新承诺((解决、拒绝)=>{ cy.get(查询)。然后((元素)=>{ 设objArray=[]; 如果(元素===未定义){ 拒绝(); } 元素。每个((索引)=>{ 让元素=元素[索引]; 设obj=cb(元素); 推送(obj); }); 解析(objArray); }); }); 返回prom; } 要在上面调用此函数,请执行以下操作:

it('get-specific-DOM-Elements',async()=>{
让data=wait-getAsync('form',getForm);
...

Cypress gitter.im的某个人这样回答,我发现这很有帮助:“您不能在Cypress上下文中运行任何类型的节点相关操作。因为您的所有代码都打包并发送到Cypress实例。例如console.log()的节点命令不会在您的测试或页面对象中运行。假设您希望清理mongo数据库表,那么您将在插件中使用index.js中的Cypress任务。对于命令,它与创建您想要创建的自定义方法一样简单,您可以在commands.js文件中执行。”一个经验法则可能是:此代码是否可以在每次回调之前进入
之前进入
?如果是,则它是一个自定义命令。例如,任务无法调用现有的
cy
命令(例如使用
cy.setCookie
设置cookie),而自定义命令可以。非常好的解释,在其他全面的cypress文档中似乎完全没有。非常棒的解释。在阅读了您的解释后,我查看了cypress文档,发现现在非常容易理解。在我的情况下,commands功能使用不足,但我想现在,我可以使用这些命令基本上,将一组类似的命令分组,用于对功能执行功能,而不是在每个测试中冗余地编写执行步骤file@Emjey当您需要描述在所有测试中都需要的行为时,自定义命令可以很好地工作