Cypress.io 如何处理异步代码 [英] Cypress.io How to handle async code

查看:43
本文介绍了Cypress.io 如何处理异步代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将旧的水豚测试迁移到 cypress.io,因为我们的应用程序正在采用 SPA 方式.

I'm in the middle of process of moving our old capybara tests to cypress.io as our application is going SPA way.

在我们的案例中,我们有 2000 多个测试涵盖了许多功能.因此,测试功能的常见模式是让用户创建和发布商品.

In our case we have over 2000 tests covering a lot of features. So common pattern to test feature is to have an user with created and published offer.

一开始我写了一个案例,其中柏树通过页面并点击所有内容.它起作用了,但我看到要约创建 + 发布花了将近 1.5 分钟才能完成.有时我们需要多个报价.所以我们有一个需要 5 分钟的测试,我们还有 1999 年要重写.

On the beginning I wrote case where cypress were going trough page and clicking everything. It worked but I saw that offer create + publish took almost 1,5 minute to finish. And sometimes we need multiple offers. So we have a test which takes 5 minutes and we have 1999 left to rewrite.

我们想出了 REST API 来创建报价和用户,基本上是测试环境准备的快捷方式.

We came up with REST API to create offer and user, basically shortcut for test env preparation.

我到了使用 async/await 一切正常的地步.所以这就是事情.如果我想在 cypress 中使用普通的异步 JS 代码,我会收到 Error: Cypress 检测到您从命令返回了一个承诺,同时还调用了该承诺中的一个或多个 cy 命令.

I came to the point where everything is working using async/await. So here's the thing. If I want to use normal async JS code with cypress I get Error: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.

这是它的样子:

    const faker = require('faker')
    import User from '../../support/User';

    describe('Toggle button for description offer', () => {
      const user = new User({
        first_name: faker.name.firstName(),
        last_name: faker.name.firstName(),
        email: `QA_${faker.internet.email()}`,
        password: 'xxx'
      })
      let offer = null

      before(async () => {
        await user.createOnServer()
        offer = await user.createOffer()
        await offer.publish()
      })

      beforeEach(() => {
        user.login()
        cy.visit(`/offers/${offer.details.id}`)
        cy.get('.offer-description__content button').as('showMoreButton')
      })

      it('XXX', function () {
        ...some test
      })
    })

此代码段按预期工作.首先它在之前触发并创建整个环境,然后当它完成时它会进一步到 beforeEach 并开始测试.

This snippet works as expected. Firstly it fires before and creates whole env then when it's done it goes further to beforeEach and starts testing.

现在我想合并之前和之前每个都喜欢

Now I would like to merge before and beforeEach like

  before(async () => {
    await user.createOnServer()
    offer = await user.createOffer()
    await offer.publish()
    user.login()
    cy.visit(`/offers/${offer.details.id}`)
    cy.get('.offer-description__content button').as('showMoreButton')
  })

这会因为 async 关键字而失败.现在的问题是:如何重写它以同时使用 async/await 和 cypress 命令?我试图用普通的 Promise 重写它,但它也不起作用......

Which will fail because of async keyword. Now the question is: how to rewrite it to use async/await and cypress commands together? I tried to rewrite it with normal Promise but It won't work too ...

感谢任何帮助.

推荐答案

您的问题源于 cypress 命令不是承诺,尽管表现得像承诺.

Your problem stems from the fact that cypress commands are not promises, although behaving like promises.

我能想到两个选择:

  • 尝试重构您的测试代码以不使用 async/await,因为在 cypress 上运行您的代码时,这些命令的行为与预期不符(检查此 错误).赛普拉斯已经有了处理异步代码的完整方法,因为它创建了一个始终按预期顺序运行的命令队列.这意味着您可以在继续测试之前观察异步代码的影响以验证它是否发生.例如,如果 User.createUserOnServer 必须等待成功的 API 调用,请使用 cy.server()、cy.route() 和 cy.wait(),如下所示:

  • Try to refactor your test code to not use async/await, as these commands don't behave as expected when running your code on cypress (check this bug). Cypress already has a whole way of dealing with async code as it creates a command queue that always run sequentially and in the expected order. That means you could observe the effects of your async code to validate that it happened before moving forward on your test. For instance, if User.createUserOnServer must wait a successful API call, add code to your test that will wait for the request to complete, using cy.server(), cy.route() and cy.wait(), like below:

cy.server();
cy.route('POST', '/users/').as('createUser');
// do something to trigger your request here, like user.createOnServer()
cy.wait('@createUser', { timeout: 10000});

  • 使用另一个第三方库来改变 cypress 与 async/await 的工作方式,例如 柏树承诺.这个库可以帮助你将 cypress 命令视为你可以在 before 代码中 await 的承诺(在这个 文章).

  • Use another third-party library that changes how cypress works with async/await, like cypress-promise. This lib may help you to treat cypress commands as promises that you can await in your before code (read more about it in this article).

    这篇关于Cypress.io 如何处理异步代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆