Проверка присутствия элемента в DOM

В автоматизированном тестировании веб-приложений на JavaScript с использованием Protractor одной из ключевых задач является проверка наличия или отсутствия элементов в DOM. Правильная реализация таких проверок позволяет создавать устойчивые и надёжные тесты, которые корректно обрабатывают асинхронные операции и динамическое поведение страниц.

Методы проверки присутствия элемента

Protractor предоставляет несколько подходов для проверки элемента: isPresent(), isDisplayed() и elementArrayFinder.count().

isPresent()

Метод isPresent() возвращает Promise, который разрешается в true, если элемент существует в DOM, и false, если его нет. При этом метод не проверяет, видим ли элемент на странице, а только факт его существования в структуре документа.

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

const myElement = element(by.css('.my-class'));

myElement.isPresent().then((present) => {
    console.log('Элемент присутствует в DOM:', present);
});

Важно учитывать, что если элемент отсутствует, вызов методов вроде getText() без предварительной проверки приведет к ошибке. Поэтому isPresent() часто используется как защита перед выполнением действий с элементом.

isDisplayed()

Метод isDisplayed() проверяет не только наличие элемента в DOM, но и его видимость на странице. Если элемент присутствует, но скрыт стилями (display: none, visibility: hidden), метод вернёт false.

Пример:

const myButton = element(by.id('submit-button'));

myButton.isDisplayed().then((visible) => {
    console.log('Кнопка видима на странице:', visible);
});

Если элемент отсутствует в DOM, вызов isDisplayed() вызовет ошибку. Чтобы избежать этого, рекомендуется сочетать его с isPresent():

myButton.isPresent().then((present) => {
    if (present) {
        myButton.isDisplayed().then((visible) => {
            console.log('Элемент присутствует и видим:', visible);
        });
    } else {
        console.log('Элемент отсутствует в DOM');
    }
});
Проверка через elementArrayFinder.count()

Когда требуется проверить наличие множества элементов или динамически создаваемых элементов, полезно использовать element.all() вместе с count().

const items = element.all(by.css('.list-item'));

items.count().then((count) => {
    if (count > 0) {
        console.log(`Элементов найдено: ${count}`);
    } else {
        console.log('Элементы отсутствуют');
    }
});

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

Асинхронность и ожидания

Protractor работает на основе WebDriver и полностью поддерживает Promise, поэтому проверки элементов необходимо выполнять с учётом асинхронности. Прямое использование isPresent() без ожиданий может привести к нестабильным тестам, особенно на страницах с динамическим контентом.

Для надёжной проверки рекомендуется использовать ExpectedConditions:

const EC = protractor.ExpectedConditions;
const myElement = element(by.css('.dynamic-element'));

// Ожидание до 5 секунд, пока элемент появится
browser.wait(EC.presenceOf(myElement), 5000).then(() => {
    console.log('Элемент появился в DOM');
});

Доступные условия для работы с элементами:

  • presenceOf(element) – элемент присутствует в DOM;
  • visibilityOf(element) – элемент видим на странице;
  • invisibilityOf(element) – элемент отсутствует или скрыт;
  • stalenessOf(element) – элемент был удалён из DOM.

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

Локаторы и влияние на проверку присутствия

Выбор локатора напрямую влияет на корректность проверки. Protractor поддерживает различные стратегии: by.id, by.css, by.xpath, by.className, by.binding и другие.

  • CSS-селекторы обычно быстрее и легче читаются, но могут не учитывать вложенность и динамические классы.
  • XPath удобен для сложной иерархии, но медленнее.
  • Angular-specific локаторы (by.binding, by.model) позволяют напрямую работать с Angular-привязанными элементами.

Пример использования Angular-локатора для проверки наличия элемента:

const usernameField = element(by.model('user.name'));

usernameField.isPresent().then((present) => {
    console.log('Поле ввода имени пользователя присутствует:', present);
});

Обработка ошибок при отсутствии элементов

Если элемент отсутствует и необходимо продолжить выполнение теста без сбоев, можно использовать цепочку catch():

myElement.isDisplayed()
    .then((visible) => console.log('Элемент видим:', visible))
    .catch(() => console.log('Элемент отсутствует или недоступен'));

Это предотвращает падение теста из-за исключений и позволяет гибко реагировать на динамические состояния страницы.

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

  1. Всегда проверять наличие элемента перед взаимодействием. Это предотвращает ошибки выполнения и делает тесты устойчивыми к изменениям DOM.
  2. Использовать ExpectedConditions для асинхронного контента. Жёсткие sleep() следует избегать.
  3. Разделять проверки на присутствие и видимость. isPresent() и isDisplayed() служат разным целям и не взаимозаменяемы.
  4. Проверка коллекций элементов через count() позволяет безопасно работать с множественными динамическими элементами.
  5. Обрабатывать исключения при отсутствии элементов. Использование catch() предотвращает падение теста и позволяет логировать состояние страницы.

Эти подходы обеспечивают стабильное тестирование и дают точное представление о состоянии элементов на странице, что особенно важно для сложных динамических интерфейсов.