Ожидание загрузки страницы в Cypress |
27.12.2023 00:00 |
Автор: Филип Рик (Filip Hric) Cypress-тест может быть очень быстрым – иногда даже быстрее тестируемого приложения. Если вы оказались в ситуации, когда Cypress работает быстрее, чем загружается ваше приложение, то эта статья для вас. Событие загрузки страницы Если вы нашли эту статью через Google, то, возможно, приступили к поиску, так как увидели сообщение «Завершено по таймауту после ожидания загрузки вашей удаленной страницы в течение 60000 мс».
Это сообщение появляется, когда страница не вызывает событие загрузки. Но что же это такое? Согласно документации MDN, событие загрузки – это нечто, вызываемое браузером после того, как он загрузил все ресурсы страницы. Что же это значит? Когда вы вводите URL в браузер и нажимаете Enter, браузер выполняет GET-запрос API к этому адресу. Это похоже на тестирование API через Postman или Cypress. Вместо получения JSON-структурированного объекта вам вернется HTML-документ. В упрощенном виде возвращенный документ будет выглядеть как-то так: 1 <html> Браузер посмотрит на этот документ и запросит все связанные с ним файлы. Заметьте, что у нас есть файлы style.css и app.js. Браузер загрузит их, и как только это сделано, вызовет событие загрузки, которого ожидает Cypress. Это в целом наилучший момент для определения готовности приложения. В реальности у многих сайтов есть файлы dynamic.js, которые начинают вызывать API загрузки ресурсов с сервера или анимировать элементы на странице. В результате страница все еще находится «в процессе загрузки». Невозможно предсказать, сколько ресурсов загрузят эти .js-файлы, и сколько времени это займет. Событие загрузки – хорошая опорная точка, но в случае с современными веб-приложениями она редко бывает последним, что со страницей произошло. Если вы получаете ошибку Cypress о невозможности загрузки страницы, то с шансами скачивание не состоялось, или же что-то его заблокировало. Возможно, проблема на вашей стороне – тогда рассматривайте ее как баг, нуждающийся в исправлении. Недавно я видел вышеупомянутую ошибку на демо-сайте Sauce Labs. Ее вызывала конфигурация вспомогательного сервиса, и в результате событие загрузки не происходило вообще. Так бывает не со всеми вспомогательными сервисами, но мне пришлось повозиться. В результате пришлось сделать заглушку для API-вызова от этого сервиса, по сути отключая его. Я добавил прерывание и перезагрузил браузер. 1 cy.intercept('/service-worker.js', { Ожидание сетевых вызововЕще один способ убедиться, что страница загружена – это дождаться сетевого вызова. К примеру, ваше приложение ведет список дел и загружает все задачи после открытия. Можно использовать перехват сетевого вызова, который будет ожидать осуществления этого вызова: 1 it('testing todos', () => { Так как cy.wait() будет ждать не только осуществления запроса, но и ответа, поэтому это надежный способ убедиться, что страница правильно загружена. Если у вас несколько вызовов API, можно перехватить все и заставить тест ожидать их осуществления, передавая массив псевдонимов в команду cy.wait(): 1 it('testing todos', () => { Другой способ ожидания нескольких запросов – применить синтаксис cy.get('@alias.all'). Так можно дожидаться всех запросов. 1 it('testing todos', () => { Тут, однако, есть две маленьких хитрости. cy.get() будет ожидать запроса лишь в течение 4000 мс, так как он слушает опцию defaultCommandTimeout, а не responseTimeout, как в случае с cy.wait(). Если ваши запросы занимают больше времени, вам нужно изменить таймаут для команды cy.get(). К тому же cy.get() будет ожидать только срабатывания запроса, а ответа ждать не будет. С этим нам может помочь встроенный в Cypress механизм повторных попыток – мы можем проверять код статуса последнего запроса, ссылаясь на него: 1 it('testing todos', () => { Ожидание DOMЕще один способ убедиться, что приложение полностью загружено – это взглянуть на DOM. Таким образом мы проверим, что не делаем ничего такого, чего не ожидаем от настоящего пользователя. К примеру, в реальности вы, скорее всего, не будете пытаться взаимодействовать с приложением, если анимация загрузки все еще перекрывает страницу. Можно добавить в тест охранное условие, проверяющее, что анимация исчезла, до начала взаимодействия со страницей. 1 it('testing todos', () => { Негативные проверки могут быть мудреными, и в зависимости от скорости страницы или специфики работы аниматора .loader может понадобиться добавить .should('be.visible') до проверки отсутствия существования элемента. Перевернем с ног на голову – можно просто воспользоваться cy.get() для первого элемента, с которым мы собираемя взаимодействовать. Если он появляется дольше, можно добавить таймаут. Про таймауты и ожидания можно прочитать в моих прошлых статьях. Таймаут по умолчаниюИногда простота – лучшее ожидание. Каждый cy.visit() будет ждать события загрузки в течение 60 секунд. Это довольно долго, потому что у реальных пользователей терпение закончится раньше. Если команда cy.visit() упадет, возможно, стоит исправлять само приложение, используя этот таймаут в качестве метрики производительности. Как вариант, можно уменьшить его, изменив опцию pageLoadTimeout в настройках. О различных таймаутах Cypress можно прочитать в его документации. |