在赛普拉斯中,何时使用自定义命令与任务?

时间:2019-11-03 13:44:09

标签: cypress

自定义命令和任务之间有什么区别?我正在尝试了解应如何使用它们。

自定义命令文档:https://docs.cypress.io/api/cypress-api/custom-commands.html

任务文档:https://docs.cypress.io/api/commands/task.html

2 个答案:

答案 0 :(得分:3)

命令cy对象上的 most 个方法)是用于将“操作”排队(推入)当前正在执行的命令队列的函数,并 serially asynchronously 执行(这就是命令的返回值具有.then方法的原因-据说,它们不是承诺,即使它们的行为有点像)。在上一个命令未完成之前,下一个命令不会执行。

命令已定义并直接在浏览器中执行(但是它们可以在浏览器外部发送消息,这就是cy.task的作用,请参见下文)。

自定义命令只不过是由用户定义的常规命令,而不是赛普拉斯开箱即用提供的默认命令。自定义命令对于自动化您一遍又一遍地在测试中重复的工作流程很有用(例如,将几个默认的cy命令组合在一起)。

命令用于与您的被测Web应用程序(AUT)进行交互-主要是与DOM交互,例如通过cy.get(selector)查询DOM;并做出断言。

认识到串行执行命令时,它们也会立即排队,并且传递给它们的任何表达式都会在那里进行评估,这一点也很重要。这不是赛普拉斯特定的行为,而是JavaScript特定的行为。这就是为什么您不能做这些事情(我经常看到这些错误经常出现)的原因:

let value;
cy.get('.myInput').invoke('val').then(val => value = val);
cy.get('.mySecondInput').type(value); // value is undefined here

任务是在赛普拉斯后端进程(节点)上定义并执行的功能,而不是在浏览器中执行。

要执行任务(您先前在cypress/plugins/index.js文件中定义),您需要首先通过cy.task(taskName, data)将它作为常规命令放入测试中。然后,赛普拉斯(当命令轮到执行时)将消息发送到后端进程(通过IPC通道---如下所述),在该进程中执行任务。

如果您的任务返回了数据,则该数据将被序列化(通过JSON.stringify或类似的东西),然后发送回浏览器,并传递到您可能使用以下方式链接到cy.task()调用的回调中.then(callback)

任务主要用于与您自己的服务器后端进行通信,例如播种数据库;或用于I / O,例如读/写文件。

据我所知,没有默认任务---您首先执行的每个任务都需要定义自己。

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

答案 1 :(得分:0)

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

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

    // INCORRECT USAGE
    let value;
    // ✗ doesn't work on Cypress commands
    const value = await cy.get('.myInput').invoke('val');
    cy.get('.mySecondInput').type(value); 

但是,有一种本机方法可以包装 cypress 命令以获得真正的 async/await 行为,如下所示:

    function getAsync(query, cb) {
      let prom = new Promise<any[]>((resolve, reject) => {
        cy.get(query).then((elements) => {
          let objArray = [];
          if (elements === undefined) {
            reject();
          }
          elements.each((index) => {
            let element = elements[index];
            let obj = cb(element);
            objArray.push(obj);
          });
          resolve(objArray);
        });
      });
      return prom;
    }

在上面调用这个函数:

  it('Gets specific DOM Elements', async () => {
    let data = await getAsync('form', getForm); 
  ...