Контекстный поиск элементов является одной из ключевых возможностей WebdriverIO, позволяющей работать с элементами страницы в определённой области DOM. Это особенно важно при тестировании сложных интерфейсов с повторяющимися компонентами или вложенными структурами. Контекстный поиск позволяет ограничить область поиска и повысить стабильность тестов.
В WebdriverIO поиск элементов осуществляется методами:
$(selector) — возвращает первый элемент,
соответствующий селектору.$$(selector) — возвращает массив всех элементов,
соответствующих селектору.Эти методы можно применять как глобально, так и относительно уже найденного элемента. Например:
const container = $('#main-container'); // глобальный поиск
const button = container.$('.submit-button'); // поиск внутри контейнера
В данном примере поиск кнопки ограничен областью
#main-container, что повышает точность и уменьшает
вероятность совпадений с элементами вне нужного блока.
WebdriverIO предоставляет несколько методов, которые применяются для поиска элементов относительно контекста:
element.$(selector) — поиск одного дочернего
элемента.element.$$(selector) — поиск всех дочерних
элементов.element.shadow$(selector) — поиск в теневом DOM (Shadow
DOM).element.shadow$$(selector) — поиск всех элементов в
теневом DOM.Применение теневого поиска:
const shadowHost = $('#shadow-host');
const shadowButton = shadowHost.shadow$('#shadow-button');
shadowButton.click();
Использование shadow$ важно для компонентов,
реализованных через Web Components, где стандартный поиск $
не сможет найти элементы внутри Shadow DOM.
WebdriverIO позволяет комбинировать контекстный поиск с ожиданиями
(waitFor*), чтобы тесты были стабильными при асинхронной
загрузке элементов. Пример:
const container = $('#dynamic-container');
const dynamicButton = container.$('.load-button');
dynamicButton.waitForExist({ timeout: 5000 });
dynamicButton.click();
Метод waitForExist ожидает появления элемента внутри
контейнера, ограничивая поиск только этим контекстом. Это исключает
ошибки, связанные с моментальным обращением к ещё не загруженному
элементу.
Контекстный поиск особенно эффективен при работе с вложенными структурами, такими как таблицы, списки или карточки. Например:
const table = $('#users-table');
const firstRow = table.$('tr:first-child');
const editButton = firstRow.$('.edit-btn');
editButton.click();
В этом примере сначала находится таблица, затем первая строка, а после этого кнопка редактирования в конкретной строке. Такой подход повышает читаемость теста и снижает вероятность выбора неверного элемента.
Методы $$(selector) и element.$$(selector)
возвращают массив элементов, что позволяет использовать итерации и
фильтрацию. Например:
const cards = $('#cards-container').$$('.card');
const activeCard = cards.find(card => card.getText().includes('Active'));
activeCard.$('.details-button').click();
В данном коде выполняется поиск всех карточек внутри контейнера, фильтрация по тексту и клик по кнопке конкретной карточки. Такой подход позволяет работать с динамическими и повторяющимися элементами интерфейса.
Часто эффективнее комбинировать глобальный и локальный поиск. Например:
const sidebar = $('#sidebar');
const menuItem = sidebar.$$('li.menu-item').find(item => item.getText() === 'Settings');
menuItem.click();
Сначала выполняется поиск контейнера бокового меню, затем локальный поиск всех пунктов меню и фильтрация нужного элемента. Это позволяет изолировать область поиска и уменьшить вероятность конфликтов с элементами, находящимися за пределами контейнера.
WebdriverIO поддерживает любые CSS и XPath селекторы при контекстном поиске. Это позволяет применять сложные выражения без необходимости глобального поиска:
const card = $('#cards-container').$(`.card[data-id="123"]`);
const button = card.$('//button[contains(text(), "Open")]');
button.click();
CSS-селектор выбирает карточку по атрибуту, а XPath используется для выбора кнопки внутри конкретного элемента. Такой подход сочетает гибкость и точность.
Контекстный поиск является фундаментальным инструментом для построения надёжных и масштабируемых тестов в WebdriverIO. Он позволяет создавать локализованные, точные и предсказуемые сценарии взаимодействия с интерфейсом, минимизируя влияние изменений в других частях страницы.