Выход из цикла while с if/else в Cypress

#javascript #jquery #testing #automation #cypress

Вопрос:

Я пишу тестовый пример, который требует, чтобы я N несколько раз перезагружал страницу и сравнивал ее заголовок для значения, если это значение не существует, то разорвите цикл while без возрастающей ошибки.

Ниже приведена демонстрационная программа, аналогичная той, которую я собираюсь реализовать.

 /// <reference types='cypress' />

it("Visiting Google",function(){
    var webUrl = 'https://html5test.com/'
    cy.visit(webUrl)
    var loop_iter = 0
    while(loop_iter < 5)
    {
        cy.get('body:nth-child(2) div:nth-child(2) div.header h1:nth-child(1) > em:nth-child(2)').then(($text_data) =>{
            if($text_data.text().contains('HTML123'))
            {
                cy.log(" --> ITERATION = ",loop_iter)
                cy.reload()
            }
            else
            {
                cy.log("Unknown website")
                loop_iter = 10
            }
        })
        loop_iter  = 1
    }
})
 

Мне нужен способ вырваться из цикла while, когда выполняется другая часть, без возникновения каких-либо ошибок.

Условие if, когда false возвращает AssertionError, в таком случае оно должно выполнить другую часть.

Комментарии:

1. Вам нужно использовать рекурсию, по крайней мере, это общий шаблон, заданный Cypress.

2. Взгляните на cypress-рекурсию . Ваш «commandsFn» будет () => cy.title() и «checkFn» будет ($text_data) => $text_data.includes('HTML') . Я еще не уверен, где это уместится cy.reload() .

3. это демонстрационный пример, я действительно хочу использовать const $val = cy.get() и сравнить, содержит ли $val строку, если она не работает, она должна выйти из while

4. Вы должны изменить вопрос, чтобы показать, чего вы действительно хотите. Кроме того, цикл while не будет работать, об этом есть много информации (некоторые из них связаны здесь).

Ответ №1:

cy.title() является асинхронным (доказательство есть, вам нужно использовать .then() ), поэтому весь while цикл заканчивается еще до первых .then() триггеров. Вот как работает асинхронизм.

Вам нужен другой подход :

 it("Visiting Google", async function () {
    var webUrl = 'https://html5test.com/'
    cy.visit(webUrl)

    for (let i = 0; i < 5; i  ) { // You can't await in a 'while' loop

        const $text_data = await cy.title();

        if ($text_data.includes('HTML')) {
            cy.log(" --> ITERATION = ", i)
            cy.reload()
        }
        else {
            cy.log("Unknown website")
            break;
        }
    }
})
 

Комментарии:

1. если я использую » const $text_data = cy.get(элемент)», то, если оператор выдает ошибку утверждения при false, необходимо выполнить блок else в таких ситуациях

2. Я не писал $text_data = cy.title() , я писал $text_data = await cy.title() . Есть огромная разница. Первый возвращает невыполненное обещание, второй-значение, которое вы ищете.

3. Просто потому, что у него есть .then() функция, это не делает его обещанием. cy.title() возвращает цепочку, с которой не работает await .

4. text_data.includes('HTML') выдает ошибку в случае, если

Ответ №2:

Пожалуйста, взгляните на перезагрузку страницы с образцами рецептов. Он использует рекурсию, как предложено в комментариях.

Это ваш код, адаптированный к шаблону,

 it('reload until "HTML" disappears', () => {

  // our utility function
  const checkAndReload = (recurse_level = 0) => {

    cy.title().then(title => {
      if (title.includes('HTML') amp;amp; recurse_level < 5) {

        cy.log(" --> ITERATION = ", recurse_level)
        cy.wait(500, { log: false })           // just breathe here
        cy.reload()                            // reload
        checkAndReload(recurse_level   1)      // check again

      } else {
        cy.log("Unknown website") 
      }
    })
  }

  cy.visit('https://html5test.com/')      // start the test by visiting the page
  checkAndReload()                        // and kicking off the first check
})