skip to Main Content

I’m struggling with waiting for async functions to finish. In particular, I found these two methods to wait for completion of an async function before the test continues but don’t know the difference (if there is one):

cy.then(() => myAsyncFunction())
cy.wrap(null).then(() => myAsyncFunction())

My goal is to wait for two async functions in the beforeEach() block before the actual tests start:

beforeEach(() => {
    myAsyncFunction1() // This function has to be completed before the next one starts
    myAsyncFunction2() // This function has to be completed before the test continues
    // Only when myAsyncFunction2() has completed the actual tests should start
});

I tried to Google for the difference and took a look in the documentation for Cypress but sadly didn’t find an answer for how this behaves.

2

Answers


  1. There are a few differences between cy.then() and cy.wrap(null).then():

    1. cy.then() – This is used to wait for the result of the previous Cypress command before continuing. Since there is no previous command in beforeEach(), cy.then() will not work.

    2. cy.wrap(null).then() – This works by wrapping a null value and chaining a .then() onto it. This allows you to execute async code before the tests run.

    3. Retries – Only commands chained after a Cypress command (like cy.get()) will be automatically retried on failure. cy.wrap(null).then() will not be retried.

    4. Yielding – cy.then() yields the result of the previous command, while cy.wrap(null).then() always yields null.

    Login or Signup to reply.
  2. There is no difference between the two calls. cy.then() is an undocumented shorter form of cy.wrap(something).then().

    cy.then() will not wait for asynchronous functions to finish in the way you are asking.

    If you want myAsyncFunction2() to wait for myAsyncFunction1(), you would use normal javascript patterns – but it depends entirely on what is inside those functions.

    cy.then() is useful to wait for the command queue to finish, particularly when the commands modify a closure variable.

    let result;
    cy.get(selector).then($el => result = $el.text())
    cy.then(() => {
      cy.log(result)    // logs the element text
    })
    

    Cypress prefers not to use closure variables, since many people have trouble understanding why the value isn’t updated in sequence. Instead they provide an alias feature to handle asynchronous variables.

    Please read Variables and aliases for more info.


    Waiting for the asynchronous functions

    As long as myAsyncFunction*() returns a promise, you just need to return that promise from beforeEach().

    Cypress always waits for returned promises to complete before moving to the next command.

    beforeEach(() => {
      return myAsyncFunction1().then(() => {
        return myAsyncFunction2()      // promise returned here will be awaited
      })
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search