DEV Community

João Pedro Costi
João Pedro Costi

Posted on

Laços de repetição com funções recursivas e comandos do Cypress

Recentemente me deparei com um problema, onde utilizava cy.wait() para esperar até que dados de um sistema passassem por alguns micro-serviços e fossem refletidos em outro sistema que era uma API, o problema é que utilizando cy.wait() os dados poderiam já terem sido refletidos, mas o Cypress ainda iria continuar esperando o tempo pré-definido.

Buscando então uma solução, pensei em criar uma forma onde o código iria ficar consultando a requisição da Api, durante um certo tempo ou até que o dado fosse refletido.

Inicialmente pensei em utilizar laços de repetição tradicionais (do, while, do while), assim colocaria uma condição onde o loop iria parar caso o número de interações chegasse ao limite ou os dados fossem refletidos na Api. Mas com Cypress isso não é possível, pelo fato desses laços de repetição serem síncronos, mas o comando (cy.request) do Cypress ser assíncrono.

Desta maneira, a outra forma que encontrei foi utilizar funções recursivas, que são funções que chamam a si mesmo até uma certa condição ser satisfeita, uma vez satisfeita a chamada das funções é encerrada.

Exemplo de função recursiva com código do Cypress

Inicialmente criei uma função que recebe como parâmetro um contador, que será o número de tentativas de consulta na API.

function recursiva(contador = 60) {
Enter fullscreen mode Exit fullscreen mode

Em seguida, inseri as informações para realizar a requisição no comando cy.request:

cy
        .request({
            method: 'GET',
            url: 'https://UrlDeExemplo.com.br',
            log: false,
            failOnStatusCode: false
        })
Enter fullscreen mode Exit fullscreen mode

Deixei a flag log desativada para não mostrar todas as requisições no console do Cypress, e também desativei a flag failOnStatusCode para o Cypress não dar erro de execução caso a requisição falhe.

Assim, uma vez o cy.request executado, eu obtenho a resposta da requisição utilizando o comando .then() e salvando o valor na variável resposta.

Dentro .then() é onde coloco as condições para encerrar a chamada de função:

  1. No primeiro if verifico se o status da resposta foi 200, isso significa que o dado foi refletido na API, assim posso encerrar a chamada das funções;

  2. Na segunda, caso o contador chegue a 0, significa que o número total de requisições que defini foi executado e as respostas das requisições continuaram não dando 200, assim considero que os dados não foram refletidos e posso acabar também a execução das funções;

  3. E por último, é caso a requisição não deu 200 e o número de requisições não foram finalizadas, assim decremento um na variável contador e chamo a função novamente passando o novo valor do contador.

.then((resposta) => {
            if (resposta.status === 200) return;
            else if (contador === 0) {
                cy.log('Os dados não foram refletidos');
                return;
            } else {
                const DECREMENTA_CONTADOR = contador - 1; 
                recursiva(DECREMENTA_CONTADOR);
            }
        });
Enter fullscreen mode Exit fullscreen mode

Juntando as partes do código, ele fica da seguinte maneira:

function recursiva(contador = 60) {
    cy
        .request({
            method: 'GET',
            url: 'https://UrlDeExemplo.com.br',
            log: false,
            failOnStatusCode: false
        })
        .then((resposta) => {
            if (resposta.status === 200) return;
            else if (contador === 0) {
                cy.log('Os dados não foram refletidos');
                return;
            } else {
                const DECREMENTA_CONTADOR = contador - 1; 
                recursiva(DECREMENTA_CONTADOR);
            }
        });
}
Enter fullscreen mode Exit fullscreen mode

O código acima pode ser adaptado de acordo com sua necessidade, o que mais é importante é a condição para parar a execução da função.

Conclusão

Utilizando funções recursivas é possível realizar laços de repetição com comandos do Cypress. O principal fato de ter optado por essa escolha foi evitar o uso de cy.wait() e assim diminuir o tempo de execução, mas ainda continuar garantido que se o dado não foi refletido para a API não foi por questão de espera de tempo.

Créditos

Créditos para o Rodrigo Matola que deu idéia de utilizar funções recursivas para resolver o problema.

Linkdin do Rodrigo: https://www.linkedin.com/in/rodrigomatola/

Meu Linkdin:
https://www.linkedin.com/in/jo%C3%A3o-pedro-costi-78a874a2/

Top comments (0)