ExpectedConditions: стандартные условия ожидания

В Protractor для работы с асинхронными действиями и динамическими элементами используется модуль ExpectedConditions (EC). Он предоставляет готовые функции для проверки состояния элементов на странице перед выполнением действий с ними. Использование EC повышает стабильность тестов и снижает вероятность ошибок, связанных с несвоевременной загрузкой элементов.


Импорт и базовое использование

Модуль ExpectedConditions доступен через объект protractor. Типичная структура импорта выглядит следующим образом:

const EC = protractor.ExpectedConditions;

Для применения условий ожидания используется метод browser.wait(), который принимает три аргумента:

  1. Условие из ExpectedConditions (функция, возвращающая true или false).
  2. Тайм-аут в миллисекундах.
  3. Сообщение об ошибке, выводимое в случае истечения времени ожидания.

Пример базового использования:

const button = element(by.id('submit'));
browser.wait(EC.elementToBeClickable(button), 5000, 'Кнопка не стала кликабельной');
button.click();

В этом примере тест будет ожидать до 5 секунд, пока кнопка не станет кликабельной, после чего выполнится клик.


Основные стандартные условия

1. elementToBeClickable(element) Возвращает true, когда элемент видим и доступен для клика. Часто используется перед click() или любым другим действием, требующим интерактивности элемента.

2. presenceOf(element) Проверяет наличие элемента в DOM. Условие возвращает true даже если элемент невидим, что полезно для проверки асинхронной загрузки элементов на странице.

3. visibilityOf(element) Проверяет видимость элемента, то есть его присутствие в DOM и отображение пользователю. Отличается от presenceOf тем, что учитывает CSS-свойства display: none и visibility: hidden.

4. invisibilityOf(element) Противоположность visibilityOf. Возвращает true, если элемент либо скрыт, либо отсутствует в DOM. Полезно для ожидания исчезновения всплывающих окон или загрузочных индикаторов.

5. textToBePresentInElement(element, text) Возвращает true, когда указанный текст присутствует в элементе. Можно использовать для проверки динамически обновляемого текста, например сообщений об ошибках или статусов загрузки.

6. textToBePresentInElementValue(element, text) Проверяет значение атрибута value у элемента формы. Применяется для проверки полей ввода.

7. titleIs(title) Проверяет, что заголовок страницы полностью совпадает с указанным текстом.

8. titleContains(titleFragment) Проверяет наличие подстроки в заголовке страницы, что удобно при навигации между динамическими страницами.

9. stalenessOf(element) Возвращает true, если элемент был удалён из DOM. Используется для ожидания исчезновения старых элементов перед созданием новых.

10. alertIsPresent() Проверяет появление модального окна браузера (alert, confirm, prompt). Возвращает true, когда алерт доступен для взаимодействия.


Комбинирование условий

Для сложных сценариев ожидания можно комбинировать условия с помощью методов:

  • EC.and(condition1, condition2, ...) — все условия должны быть истинными.
  • EC.or(condition1, condition2, ...) — хотя бы одно из условий должно быть истинным.
  • EC.not(condition) — возвращает противоположное значение.

Пример комбинации:

const modal = element(by.css('.modal'));
browser.wait(
  EC.and(
    EC.visibilityOf(modal),
    EC.textToBePresentInElement(modal, 'Загрузка завершена')
  ),
  7000,
  'Модальное окно не появилось с ожидаемым текстом'
);

Здесь тест ожидает появления модального окна с конкретным текстом одновременно.


Практические советы

  • Использовать тайм-ауты в browser.wait(), соответствующие сложности страницы и времени загрузки. Оптимальное значение обычно 5000–10000 мс для динамических элементов.
  • Не применять жесткие browser.sleep(), если есть возможность использовать EC, чтобы тест оставался стабильным и быстрым.
  • Предпочтительно проверять видимость элементов (visibilityOf) перед кликами, даже если элемент присутствует в DOM, чтобы избежать ошибок ElementNotInteractable.
  • При проверке изменения текста лучше использовать textToBePresentInElement, чтобы тест ждал фактического обновления данных.
  • Для элементов, которые исчезают после действия, использовать stalenessOf, что предотвращает попытки взаимодействия с устаревшими элементами.

Пример комплексного сценария

const loginButton = element(by.id('login'));
const usernameInput = element(by.id('username'));
const passwordInput = element(by.id('password'));
const errorMessage = element(by.css('.error'));

browser.wait(EC.visibilityOf(usernameInput), 5000, 'Поле username не появилось');
usernameInput.sendKeys('testuser');

browser.wait(EC.visibilityOf(passwordInput), 5000, 'Поле password не появилось');
passwordInput.sendKeys('12345');

browser.wait(EC.elementToBeClickable(loginButton), 5000, 'Кнопка login недоступна');
loginButton.click();

browser.wait(EC.or(
    EC.invisibilityOf(errorMessage),
    EC.stalenessOf(errorMessage)
), 7000, 'Ошибка при логине осталась видимой');

Этот пример демонстрирует полное управление ожиданиями: сначала проверка видимости полей ввода, затем кликабельность кнопки и, наконец, проверка исчезновения сообщения об ошибке.


Использование ExpectedConditions обеспечивает предсказуемость и устойчивость тестов в Protractor, особенно при работе с динамическими страницами и асинхронными операциями.