Shadow DOM — это технология, которая позволяет инкапсулировать часть DOM-дерева внутри элемента. Это позволяет создать изолированную область, которая может содержать собственный стиль и структуру, не влияя на внешний DOM. Каждый элемент с Shadow DOM имеет своё локальное дерево, которое не пересекается с основным документом, что делает его мощным инструментом для разработки компонентных библиотек и интерфейсов.
При работе с WebdriverIO важно уметь правильно находить элементы внутри таких Shadow DOM, поскольку стандартные методы поиска элементов не всегда работают в этом контексте. В этой статье подробно рассмотрим, как взаимодействовать с Shadow DOM элементами в WebdriverIO.
Элементы внутри Shadow DOM находятся в контексте своего родительского
компонента. Это означает, что стандартные методы поиска элементов, такие
как $$ или $("#element"), не будут работать
для поиска внутри Shadow DOM. Для того чтобы взаимодействовать с
элементами, расположенными внутри такого DOM, необходимо использовать
специальные методы для получения доступа к внутреннему дереву
компонента.
Основная проблема при тестировании с использованием Shadow DOM заключается в том, что мы не можем просто получить доступ к элементу через стандартный селектор. Нужно сначала получить сам элемент, который содержит Shadow DOM, а затем найти нужный элемент внутри этого инкапсулированного контекста.
Для работы с элементами внутри Shadow DOM можно использовать метод
shadowRoot. Этот метод позволяет получить доступ к корню
Shadow DOM компонента и затем выполнять поиск внутри него.
Пример кода, который демонстрирует, как найти элемент внутри Shadow DOM:
const shadowHost = await $('#shadow-host'); // Находим элемент, который содержит Shadow DOM
const shadowRoot = await shadowHost.shadowRoot; // Получаем доступ к Shadow DOM
const shadowElement = await shadowRoot.$('.element-inside-shadow'); // Ищем элемент внутри Shadow DOM
В данном примере:
shadowRoot, который
является корнем этого компонента.shadowRoot, мы можем
использовать стандартные методы поиска, такие как $, чтобы
находить элементы внутри Shadow DOM.shadowRoot. Для этого нужно будет несколько раз
обратиться к shadowRoot, чтобы перейти на нужный
уровень.Пример с вложенным Shadow DOM:
const firstShadowHost = await $('#first-shadow-host');
const firstShadowRoot = await firstShadowHost.shadowRoot;
const secondShadowHost = await firstShadowRoot.$('#second-shadow-host');
const secondShadowRoot = await secondShadowHost.shadowRoot;
const elementInsideSecondShadow = await secondShadowRoot.$('.final-element');
Пример использования ожидания:
const shadowHost = await $('#shadow-host');
const shadowRoot = await shadowHost.shadowRoot;
await shadowRoot.$('.element-inside-shadow').waitForDisplayed({ timeout: 5000 });
click(), setValue(),
getText() и другие.const shadowHost = await $('#shadow-host');
const shadowRoot = await shadowHost.shadowRoot;
const shadowButton = await shadowRoot.$('button');
await shadowButton.click();
WebdriverIO позволяет расширять возможности поиска с помощью пользовательских селекторов. Это может быть полезно, если требуется часто работать с элементами внутри Shadow DOM и хочется упростить код.
Пример кастомного селектора для поиска внутри Shadow DOM:
browser.addCommand('shadow', function(selector) {
return this.$(selector).shadowRoot;
});
// Применение кастомного селектора
const shadowRoot = await browser.shadow('#shadow-host');
const shadowElement = await shadowRoot.$('.element-inside-shadow');
Таким образом, с помощью кастомных команд можно упростить процесс работы с элементами внутри Shadow DOM, улучшая читаемость и поддержку тестов.
Иногда может возникнуть ситуация, когда требуется взаимодействовать с элементами, которые находятся за пределами Shadow DOM, но всё равно связаны с ним. В таком случае важно сначала получить доступ к Shadow DOM и затем искать элементы в его контексте.
Пример:
const shadowHost = await $('#shadow-host');
const shadowRoot = await shadowHost.shadowRoot;
const outsideElement = await $('#outside-element'); // Элемент за пределами Shadow DOM
await shadowRoot.$('.element-inside-shadow').click();
await outsideElement.click(); // Взаимодействие с элементом за пределами Shadow DOM
Работа с Shadow DOM в WebdriverIO требует особого
подхода и использования специфических методов для доступа к элементам
внутри инкапсулированных деревьев DOM. Основной задачей является
получение доступа к shadowRoot и дальнейшее взаимодействие
с элементами внутри этого контекста. Важно учитывать возможные проблемы
с динамическим контентом и многократным вложением Shadow DOM. Умение
работать с этими особенностями значительно улучшает возможности
тестирования современных веб-приложений, использующих веб-компоненты и
Shadow DOM.