Явные ожидания и waitUntil

В WebdriverIO явные ожидания используются для управления синхронизацией тестов с состоянием веб-страницы. Они позволяют не полагаться на фиксированные задержки (sleep) и гарантируют выполнение действий только тогда, когда элементы или условия готовы для взаимодействия.


Основные методы явных ожиданий

WebdriverIO предоставляет несколько ключевых команд для явных ожиданий:

  • waitForExist — ожидание появления элемента в DOM.
  • waitForDisplayed — ожидание, что элемент видим на странице.
  • waitForEnabled — ожидание, что элемент доступен для взаимодействия.
  • waitForClickable — ожидание, что элемент можно кликнуть.
  • waitUntil — универсальный метод ожидания для произвольных условий.

Каждый метод принимает таймаут и сообщение ошибки, которые помогают детально управлять поведением теста.

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

const button = await $('#submit');
await button.waitForDisplayed({
    timeout: 5000,
    timeoutMsg: 'Кнопка "Submit" не появилась в течение 5 секунд'
});
await button.click();

Здесь тест приостановится до появления кнопки, избегая ненадёжных задержек.


Универсальное ожидание через waitUntil

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

Синтаксис:

await browser.waitUntil(
    async () => {
        const text = await $('#status').getText();
        return text === 'Готово';
    },
    {
        timeout: 7000,
        timeoutMsg: 'Статус не обновился на "Готово" за 7 секунд',
        interval: 500
    }
);

Пояснение параметров:

  • timeout — максимальное время ожидания в миллисекундах.
  • timeoutMsg — сообщение об ошибке, если условие не выполнено.
  • interval — период проверки условия (по умолчанию 500 мс).

Примеры сложных условий

Ожидание изменения стиля элемента:

await browser.waitUntil(
    async () => {
        const color = await $('#notification').getCSSProperty('color');
        return color.parsed.hex === '#00FF00'; // зелёный
    },
    {
        timeout: 6000,
        timeoutMsg: 'Цвет уведомления не стал зелёным'
    }
);

Проверка наличия текста среди нескольких элементов:

await browser.waitUntil(
    async () => {
        const items = await $$('.list-item');
        return items.some(async item => (await item.getText()) === 'Завершено');
    },
    {
        timeout: 8000,
        timeoutMsg: 'Нет элемента со статусом "Завершено"'
    }
);

Важные рекомендации при использовании явных ожиданий

  1. Минимизировать статические задержки — фиксированные sleep делают тесты медленными и ненадёжными.
  2. Использовать подходящие команды ожидания для каждого случаяwaitForDisplayed для видимости, waitForClickable для кликабельности.
  3. Добавлять информативные сообщения об ошибках — ускоряет диагностику при падении тестов.
  4. Комбинировать условия через waitUntil — при необходимости проверять несколько состояний одновременно.
  5. Не злоупотреблять слишком короткими таймаутами — динамичные веб-приложения могут временно задерживать изменения элементов.

Практическая оптимизация

WebdriverIO позволяет создавать обёртки над waitUntil для повторного использования условий:

async function waitForStatusReady(selector, timeout = 5000) {
    await browser.waitUntil(
        async () => (await $(selector).getText()) === 'Готово',
        {
            timeout,
            timeoutMsg: `Статус элемента ${selector} не стал "Готово" за ${timeout} мс`
        }
    );
}

Это повышает читаемость тестов и снижает дублирование кода.


Особенности работы в асинхронном режиме

WebdriverIO использует промисы, поэтому все явные ожидания требуют await. Без него проверка может завершиться преждевременно, и условие никогда не дождётся нужного состояния:

// Плохо
browser.waitUntil(() => $('#status').getText() === 'Готово');

// Правильно
await browser.waitUntil(
    async () => (await $('#status').getText()) === 'Готово'
);

Асинхронность критична при проверке текста, CSS-свойств или других динамических атрибутов.


Резюме ключевых моментов

  • Явные ожидания делают тесты надёжными, синхронизируя действия с реальным состоянием страницы.
  • waitForDisplayed, waitForExist, waitForClickable подходят для типичных проверок.
  • waitUntil обеспечивает гибкость для сложных или кастомных условий.
  • Всегда указывать таймауты и сообщения об ошибках для стабильности тестов.
  • Асинхронные функции и await обязательны при работе с промисами WebdriverIO.