1

With my team we're trying to find a more readable way to handle dependent API calls in Cypress. We have some code just like this nowadays:

// nested code
      cy.request('GET', myUrl).its('body').then(res => {
        cy.request('GET', res).its('body').then(subRes => {
          cy.request('GET', subRes).its('body').then(subSubRes => {
            expect(subSubRes, myMessage).to.eq(myEvaluation);
          })
        })
      })

We have thought about this solution also but I think we doesn't gain a lot in readability.

// less nested code?
      let response;
      let subResponse;
      cy.request('GET', myUrl).its('body').then(res => {
        response = res;
      })
      
      cy.then(() => {
        cy.request('GET', response).its('body').then(subRes => {
          subResponse = subRes;
        })
      })

      cy.then(() => {
        cy.request('GET', subResponse).its('body').then(subSubRes => {
          expect(subSubRes, myMessage).to.eq(myEvaluation);
        })
      })

Do you have any ideas to handle this kind of logic without getting into a pyramid? Thanks in advance!

Gonzalo Diaz Ailan
  • 583
  • 1
  • 5
  • 23
  • 1
    Does this answer your question? [How to avoid indented nested promises?](https://stackoverflow.com/questions/65514612/how-to-avoid-indented-nested-promises) – Ivar Jul 13 '22 at 10:03
  • Not really. The answer of mbojko adds new info that is not covered in the thread that you provided. It was not clear for me by the answer provided in the other thread that I could pass the return value of a .then() as an argument for the anonymous function of the next .then() so my team and I find that answer valuable and I'd prefer to keep this question open. – Gonzalo Diaz Ailan Jul 25 '22 at 15:21

2 Answers2

12

Something like

cy.request('GET', myUrl).its('body')
    .then(res => cy.request('GET', res).its('body'))
    .then(subRes => cy.request('GET', subRes).its('body'))
    .then(subSubRes => {
        expect(subSubRes, myMessage).to.eq(myEvaluation);
    });

should work.

mbojko
  • 13,503
  • 1
  • 16
  • 26
  • 1
    That's right. Many peoply tend to miss the fact that the `then()`'s are chainable: if the callback from a `then()` returns a value, that value will be available to the next `then()`; more importantly, if the value returned is, itself, a `Promise`, it's result will be returned to the next chained `then()` only *after it is, itself, resolved*. The code above makes use of this elegant feature. – Haroldo_OK Jul 13 '22 at 10:18
-4

Please use Promise resolve : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

cy.request('GET', myUrl).its('body')
    .then(res => cy.request('GET', res).its('body'))
    .then(res => cy.request('GET', res).its('body'))
    .then(res => {
        expect(res, myMessage).to.eq(myEvaluation);
    });
}

Jay
  • 2,826
  • 2
  • 13
  • 28
  • 4
    Cypress Commands are not promises, and the Cypress developers do not recommend using async/await with Cypress. https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#The-Cypress-Command-Queue – agoff Jul 13 '22 at 13:36
  • 4
    In fact ***cannot*** use async/await. – Fody Jul 13 '22 at 21:02