randompromisecypressnode-oracledbcypress-task

How to loop cy.task according to the result


I'm testing the CRUDs for a page in my application, where a registry requires an unique ID as a 5 digit number to be successfully created.

I would like to get a random available ID of that table to use in the tests, that can be achieved with the following sql query:

    cy.task(
      'sqlQuery',
      `select count(*) as "count" from clients where client_id = '${
        Math.floor(Math.random() * 90000) + 10000
      }'`
    )

The point is that the random number perhaps is not available to be used as the ID, so i would need to loop this same task until the generated number is available:

    cy.task(
      'sqlQuery',
      `select count(*) as "count" from clients where client_id = '${
        Math.floor(Math.random() * 90000) + 10000
      }'`
    ).then((result: any) => {
      if (result.rows[0].count === 0) {
        // My code to submit the form with the generated number
        // break the loop
      } else {
        // Repeat all of this (where i'm asking for help)
      }
    })

If count returns 0 it means it's there's no registry using it, otherwise it's not available.

I guess the final solution could be using some while loop, but I found this way would be more clear to you all know what i'm needing.

I tried some approachs like this, but just discovery that its impossible to assign a new value to a variable inside the .then block, so it seems like i did an endless loop.

    let available = false
    do {
      cy.task(
        'sqlQuery',
        `select count(*) as "count" from clients client_id = '${
          Math.floor(Math.random() * 90000) + 10000
        }'`
      ).then((result: any) => {
        if (result.rows[0].count === 0) {
          // Code to submit the form with the generated number
          available = true
        }
      })
    } while (available === false)

Solution

  • Ask SQL what ids are present and check the random one against those?

    Something like this:

    cy.task('sqlQuery', 'select client_id from clients')
      .then((result: any) => {
        const ids: string[] = result.rows;
    
        function getNewId(trys = 0) {
          if (trys > 1000) throw new Error('failed')
          const newId = Math.floor(Math.random() * 90000) + 10000
          if (ids.includes(newId)) {
            return getNewId(++trys)
          }
          return newId
        }
    
        const newId = getNewId()
        cy.wrap(newId).as('newId')
      })
    

    Update

    Changed to a recursive javascript function, as I found when testing .should() it does not re-evaluate Math.floor(Math.random() * 90000) + 10000


    It's been a while since I did some SQL, but maybe this correlated subquery is more efficient

    SELECT last + 1 as newId FROM (
      SELECT MAX(id) as last FROM clients
    )