XPATH, вверх и вниз по DOMу
Итак, мы посмотрели как писать локаторы XPATH, как писать CSS, договорились не копировать локаторы слепо и по возможности писать кратко и понятно.
Напоминаю алгоритм написания любого локатора:
1) Если есть, то используем уникальный id или имя класса
2) Если не выполняется пункт 1, то идем к разработчикам и просим его обеспечить
3) Если не выполняется пункт 2, то пытаемся использовать CSS, если можно написать коротко
4) Keep calm and use XPATH
Сегодня я покажу написание локаторов на небольшом и конечно искусственном примере, который показывает, что не всегда можно использовать CSS или другие локаторы. Перед нами сайт дорого во всех смыслах Ростелеком, с предложениями по интернет: https://spb.rt.ru/packages/tariffs
В тестах нам нужно нажать кнопку «Подключить» у тарифа с ценой 1010 рублей. Но мы при этом знаем, что тарифы часто меняются и данный тариф с его кнопкой может быть расположен в любом месте страницы, с любым id. (На самом деле задача реальная, но любые совпадения случайны)
Исходя из условий, мы не можем просто получить список кнопок с надписью «Подключить» и кликнуть вторую, в любой момент она может стать третьей. Мы также не можем быть уверены, что id тарифа не изменится, кроме того, было бы круто иметь один общий локатор, который бы нашел кнопку «Подключить» у тарифа по его цене. Класс также не уникален и возвращает список элементов.
Что же есть уникальное, к чему можно прицепиться? Цена тарифа! У всех тарифов разные цены, причем в данном случае мы как раз ищем цену 1010 рублей.
У элемента цены есть уникальный атрибут data-fee=’1010′ по которому мы можем точно найти его, причем только его одного.
//*[@data-fee=’1010′] — мы точно находим нужную цену. Теперь нужно двигаться к кнопке Подключить по дереву DOM и тут есть два варианта:
1) подняться от цены к ее родителю ( class =» tariff-desc__cost_m-cell «), от него получить следующий сестринский элемент ( class =» tariff-desc__cost_l-cell «) и уже в нем получить кнопку. Получается один шаг вверх и два вниз
//*[@data-fee=’1010′]/.. — переходим к родителю
//*[@data-fee=’1010′]/../following-sibling::div — уходим вниз к сестринскому элементу
//*[@data-fee=’1010′]/../following-sibling::div/a — получаем нашу кнопку
2) так как кнопка Подключить и цена входят в состав одного блока, то гораздо лучше от цены найти ее предка (не непосредственного родителя!), который является этим блоком ( class =» tariff-desc__cost tariff-desc__cost_reset js-price-blocks «) у него просто взять вложенный элемент кнопки. Получается всего два шага -вверх и вниз
//*[@data-fee=’1010′]/ancestor::div[contains(@class,’js-price’)] — получаем предка(ancestor), с классом содержащим js-price
//*[@data-fee=’1010′]/ancestor::div[contains(@class,’js-price’)]//a — у нашего элемента просто ищем вложенную ссылку (нашу кнопку).
Можете убедиться, что оба локатора являются уникальными, и меняя цену, можно получать локаторы кнопки у всех остальных тарифов по их цене.
Я чаще всего работаю с элементами во вкладке Элементы инструментов разработчика браузера, чтобы видеть соседние элементы, предков и вообще дерево DOM. Но иногда удобнее проверять локаторы во вкладке Консоль, набрав команду вида $x(«выражение») , там видно только конкретно найденные элементы
Надеюсь вам никогда не придется идти в алгоритме поиска элемента дальше 1 пункта.
Источник