Cypress wait-until plugin issue: cy.then() failed because you are mixing up async and sync code

67 Views Asked by At

I've got this helper function that is supposed to wait until status equals 'SENT'.

function waitForSENTStatusDB(GWuuid: string) {
        cy.log("wait for status 'SENT' in DB");
        cy.waitUntil(() => {
            const BodyToUse = "SELECT * FROM table where entity_id = '{GWID}' order by last_modified_at desc".replaceAll("{GWID}", GWuuid);

            DB.Generic(BodyToUse).then((res) => {
                let status = res[0].status;
                cy.log("Current status: " + status);
                return status === INTERFACES.UploadStatus.SENT;
            });
            }, {
                errorMsg: "Timeout: Upload status is not 'SENT'",
                interval: 10000,
                timeout: 200000
            }
            )
        }

I'm calling the function in an 'it' block in Cypress:

it(`(Iteration: config changed = ${item.PAYLOAD_CHANGE.configurationChanged})Check/Wait for entity state - status SENT (via DB)`, () => {
            waitForSENTStatusDB(GWid);
        });

The function is waiting properly and everything but once I the helper function returns true to move on to the next it block, Cypress gives me the following error during execution:

cy.then() failed because you are mixing up async and sync code.

In your callback function you invoked 1 or more cy commands but then returned a synchronous value.

Cypress commands are asynchronous and it doesn't make sense to queue cy commands and yet return a synchronous value.

You likely forgot to properly chain the cy commands using another cy.then().

The value you synchronously returned was: true

I'm new to Cypress, I tried everything that came to my mind.

After the helper function with waitUntil() returns true, the execution will move on to the next it block.

2

There are 2 best solutions below

2
Lort.Nielsen On

The waituntil command is limited, but you can substitute a plain javascript function to repeat the command.

Since you already wrap with a function, add a counter to the parameters and repeat call if the condition is not met.

function waitForSENTStatusDB(GWuuid, times: 0) {

  cy.log("wait for status 'SENT' in DB", times);

  if (times > 20) {    // counter = timeout/interval
    throw new Error("Timeout: Upload status is not 'SENT'")
  }

  const bodyToUse = `SELECT * FROM table where entity_id = '${GWuuid}' order by last_modified_at desc`

  DB.Generic(bodyToUse).then((res) => {
    let status = res[0].status;
    cy.log("Current status: " + status)

    if (status !== INTERFACES.UploadStatus.SENT) {
      cy.wait(10000)
      waitForSENTStatusDB(GWuuid, ++times)
    }
}


waitForSENTStatusDB('123')
0
Balmorax On

The issue was using the cy.log function within the waitUntil. Don't ask me for technical reasons, but simply substituting it with console.log helped.