Как создать синхронный цикл for?

Я хочу щелкнуть несколько элементов на веб-странице и проверить, создает ли каждое из этих действий правильный URL-адрес запроса API. Для этого я создал массив настроек для каждого элемента и перебрал их, щелкнул соответствующий элемент и подтвердил результаты. Проблема в том, что утверждение для последнего элемента всегда ожидает установки для первого элемента. Я вижу, что это происходит потому, что кипарис работает асинхронно. Итак, я удалил итерацию и просто повторил все утверждения-действия, как показано ниже.

Есть ли простой способ сделать синхронный цикл for вместо того, как я это сделал ниже? По сути, я хочу преобразовать последовательность .then() в цикл for. «Действие» — это нажатие элемента на странице на основе объекта actionSettings. Этот объект может выглядеть примерно так: {age: 23, gender: male}. ОБРАТИТЕ ВНИМАНИЕ, что я не хочу использовать здесь плагин рекурсии кипариса.

//code to intercept api call aliased as "actionApiCall".

cy.log("Do 1 of 5 actions on a given page")
  .then(() => {
    const actionSettings = getActionSettings("for action 1");
    myPageObject
      // clickElement(...) returns a Cypress.Chainable<null> with return cy.wrap(null);
      .clickElement(actionSettings)
      .wait("@actionApiCall")
      .then((intercept) => {
        // This assertion checks that the query params of the request URL are per the settings in actionSettings.
        AssertActions.assertActionRequest(intercept.request, actionSettings);
      });
}).log("Do 2 of 5 actions on a given page")
  .then(() => {//do stuff})
.log("Do 3 of 5 actions on a given page")
  .then(() => {//do stuff})

..... ETC

PS — Cypress .each здесь не будет работать, потому что я не хочу перебирать элементы кипариса. Я хочу перебирать массив «actionSettings», то есть не элементы кипариса. Кроме того, вот решения, которые мне не помогли.

Как я могу запустить команду Cypress в синхронном цикле?

https://stackoverflow.com/a/72512125/6648326

https://stackoverflow.com/a/70687033/6648326

Многие детали скрыты вашим пользовательским кодом, и мы можем только догадываться, что он делает. Полагаю, вы спрашиваете: «Как мне преобразовать последовательность .then() в цикл».

Angus Yaam 06.06.2024 00:12

Какие именно действия? Есть ли другие методы AssertActions.assertActionRequest? то есть не могли бы вы примерно показать, что такое do stuff для №2 и №3, пожалуйста?

Angus Yaam 06.06.2024 00:14

@AngusYaam - спасибо. Да, я хочу преобразовать последовательность .then() в цикл for. Действия для №2 и №3 в основном такие же, как и для №1. «Действие» — это действие по щелчку элемента на странице на основе объекта actionSettings. Этот объект может выглядеть примерно так: {age: 23, gender: male}. Пожалуйста, дайте мне знать, если это поможет, или мне нужно объяснить это лучше.

MasterJoe 06.06.2024 04:21

Хорошо, спасибо, думаю, теперь я вижу закономерность.

Angus Yaam 06.06.2024 07:46

Я не могу опубликовать код, но использую Аладина - массив для цикла будет выглядеть примерно так ['for action 1', 'for action 2', 'for action 3']. Затем я помещал общий код в функцию и передал каждую клавишу действия в качестве параметра (это все простой forEach() код). Я согласен с комментариями о создании утверждений для «регулирования» потока, которые кажутся правильным способом заставить цикл вести себя синхронно.

Angus Yaam 06.06.2024 07:51
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
5
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, вы просто хотите обернуть каждый шаг в .then(), чтобы гарантировать, что очередь Cypress обрабатывается в том же порядке, что и ваша последовательность выше.

Не думайте о асинхронности/синхронности, вместо этого подумайте об очереди команд, которую Cypress использует в качестве конвейера команд. Когда вы выполняете цикл по некоторому массиву, использование .then() гарантирует, что команды находятся в правильной последовательности.

Если действие вызывает изменение страницы, вам нужно будет добавить после каждого утверждения утверждение should(), подтверждающее завершение действия. Что-то вроде:

const actionsArray = [action1, action2, action3]
actionsArray.forEach(action => {
  cy.then(() => {
    action() // perform action in sequence
      .should(assert action is complete)
  })
})

// or
cy.wrap(actions).each(action => {
  cy.then(() => {
    action() // perform action in sequence
      .should(assert action is complete)
  })
})

логически эквивалентно

action1()
  .should(assert something that indicates action1 is complete)
  .then(() => {
    action2().should(assert action is complete)
  })
  .then(() => {
    action3().should(assert action is complete)
  })

Есть и другие вопросы, которые следует учитывать, например, что делать, если действия зависят от некоторых данных, которые обновляются на разных этапах.

Похоже, ваш массив действий будет массивом функций для запуска. Это верно? Почему мы не можем вместо этого перебирать actionSettings? actionsettings — это объект типа {age: 23, gender: male}

MasterJoe 06.06.2024 04:41

Да, извините, я неправильно понял вопрос.

Aladin Spaz 12.06.2024 06:25

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

Aladin Spaz 12.06.2024 06:33

Другие вопросы по теме