Разделы портала

Онлайн-тренинги

.
Основы Cypress: выбор элементов
11.05.2023 00:00

Автор: Филип Рик (Filip Hric)
Оригинал статьи
Перевод: Ольга Алифанова

Эта статья – часть серии "Основы Cypress". В этой серии я попытался пошагово объяснить базовые вещи. Если вы хотите узнать больше, открывайте любую статью серии.

Селекторы – это больно, особенно если вы только начинаете автоматизировать тесты. Недавно на воркшопе по Cypress я видел, как людям трудно с селекторами – это было связано с тем, что они использовали другой подход к выбору элементов на странице. В этой статье я хочу рассказать об основах выбора элементов на странице при помощи Cypress.

На моей Github-странице есть репозиторий, где вы найдете все примеры из статьи.

Выбор одного элемента

В Cypress элементы выбираются при помощи следующего синтаксиса:

cy.get('.selector')

Для начала разберемся, что идет в части .selector. Cypress выбирает элементы, опрашивая DOM. Возможно, вы уже знакомы с такими селекторами, если имели дело с CSS, использовали jQuery или знаете команду document.querySelector в JavaScript. Посмотрим, что же это значит. В качестве примера возьмем страницу, которая выглядит примерно так:


Для выбора элементов, конечно, жизненно важно заглянуть внутрь страницы. Разметка нашей страницы выглядит так:

<h1>Shapes:</h1>
<div></div>
<div id="circle"></div>
<div shape="triangle"></div>

Мы можем выбрать элемент, используя тег h1. Если нам нужно выбрать одну фигуру, можно выбрать один элемент, используя класс, id или атрибут.

cy
.get('h1') // выбор по тегу
.get('.square') // выбор по классу
.get('#circle') // выбор по id
.get('[shape="triangle"]'); // выбор по атрибуту

Чтобы выбрать элемент по классу, нужно использовать . – префикс, а для выбора элемента по id нужно сначала поставить префикс #. Наиболее распространенный атрибут на странице – это заменитель ввода или даже тест-id, когда селектор начинается и заканчивается квадратными скобками. Если мы хотим выбрать элемент, который встречается на странице несколько раз, как наш элемент div, Cypress выберет все из них. Попробуйте сами!

Выбор дочерних элементов

При работе с вложенными элементами их часто называют дочерними. Логика вложенности очень проста. Дочерний элемент находится в родительском. Каждый элемент может быть и дочерним, и родительским в зависимости от его отношений с другим элементом. В следующем примере у нас html-страница с такой структурой:

<div class="square-big red">
<div></div>
</div>
<div class="square-big green">
<div></div>
</div>
<div class="square-big green">
<div>
<div></div>
</div>
</div>

Это простая и, надеюсь, читабельная структура. У всех зеленых элементов есть класс .green, а все круглые элементы имеют класс .circle. На второй строке находится элемент, имеющий оба этих класса. Это вернет зеленый круг. Я сделал скриншот реальной страницы. Подумайте минутку над тем, как html-код соответствует отрисовке страницы (я, кстати, не включил в html-код заголовки):


Для начала сконцентрируемся на внутренних кружочках. Если выбирать круг по классу, используя cy.get('.circle'), вернутся все три элемента. Но нам, возможно, нужно сузить выбор. Это можно сделать, уточнив селектор. Что, как вы думаете, вернет этот селектор?

cy
.get('.green .circle')

Правильный ответ – круги в квадратах 2 и 3. Этот селектор будет искать все элементы .circle, находящиеся внутри любого элемента .green. Как можно видеть, оба они находятся в элементе .green, большом зеленом квадрате.

Теперь предположим, что нам нужно выбрать только круг внутри второго квадрата. Иными словами, если круг внутри красного квадрата, мы его игнорируем. В нашем случае это будет выглядеть так:

cy
.get('.green > .circle');

Этот селектор выберет только те элементы .circle, у которых элемент .green на один уровень выше. Так как в третьем квадрате элемент .circle вложен в элемент .red, он не будет выбран.

Для выбора элементов есть масса способов, и команда .get() хорошо работает практически в каждом из них (я говорю "практически", так как нельзя использовать псевдоселекторы вроде :hover или :visited). Целую кучу селекторов можно найти на странице W3 schools. Их освоение окажет вам неоценимую помощь в создании тестов и понимании DOM-структуры вашей страницы.

Команды Cypress для выбора элементов

Освоение различных CSS-селекторов – это, безусловно, полезно, но выбрать элементы на странице можно массой способов при помощи команд Cypress. Важно отметить, что эти команды куда читабельнее в тестах. В этом примере мы будем тестировать эту симпатичную радужную страничку:


Выбор по тексту

Для выбора элемента по содержащемуся в нем тексту можно использовать команду .contains. Она очень похожа на одноименный метод jQuery. Команду можно использовать по-разному:

// выбор элемента с текстом "indigo"
cy
.contains('indigo')
// выбор элемента h1, содержащего текст "Rainbow"
cy
.contains('h1', 'Rainbow')

Можно даже объединять команды в цепочки, создавая, как мне кажется, довольно-таки самоочевидный код. Код ниже будет искать элемент li (элемент списка) внутри списка .list. Он найдет несколько элементов, а из них мы выберем элемент с текстом "purple".

cy
.get('.list')
.find('li') // возвращает 7 элементов li
.contains('violet') // возвращает один элемент

Выбор по позиции в списке

Внутри списка элементы можно выбирать по их позиции в списке, используя селекторы first(), .last() или .eq().

cy
.get('li')
.first(); // выбрать "red"
cy
.get('li')
.last(); // выбрать "violet"
cy
.get('li')
.eq(2); // выбрать "yellow"

Можно также выбрать элемент по отношению к уже выбранному элементу. Скажем, можно выбрать элемент .blue, используя команду .next():

cy
.get('.green')
.next(); // выберет элемент .blue

И, конечно, можно поступить наоборот:

cy
.get('.green')
.prev(); // выберет элемент .yellow

Выбор элементов через фильтрацию

Когда вы выбрали несколько элементов (например, через команду .get('li'), возвращающую 7 элементов), их можно отфильтровать на основании другого селектора. Код ниже выберет только красный, зеленый и синего цвета, так как это основные цвета с классом .primary.

cy
.get('li')
.filter('.primary') // выбор всех элементов с классом .primary

Чтобы сделать ровно наоборот, можно использовать команду .not(). Эта команда выберет все цвета, кроме красного, зеленого и синего.

cy
.get('li')
.not('.primary') // выбор всех элементов без класса .primary

Поиск элементов

Селектор можно уточнить, сначала выбрав элемент, в котором мы собираемся искать, а затем просматривая структуру DOM для поиска конкретного элемента.

cy
.get('.list')
.find('.violet') // найдет элемент с классом .violet внутри элемента .list

Вместо просмотра DOM-структуры вниз и поиска элемента внутри другого элемента можно искать и вверх. В этом примере мы сначала выбираем элемент списка, а затем пытаемся найти элемент с классом .list.

cy
.get('.violet')
.parent('.list') // находит элемент с классом .list, который выше нашего элемента .violet

Что дальше?

Для получения нужного элемента эти команды можно комбинировать любым образом. Однако не слишком увлекайтесь. Самый чистый способ выбора элементов в Cypress – убедиться, что в вашем приложении действительно есть необходимые селекторы. Хорошая практика – добавлять свои собственные атрибуты data-test к тем элементам приложения, с которыми вы хотите взаимодействовать. Более того, если затем воспользоваться интерактивной средой Cypress Selector, можно быстрее найти нужные селекторы – Cypress предпочитает селекторы классам, id и другим атрибутам. Однако можно легко уточнить, какие селекторы должен предпочитать сервис интерактивной среды.

Если вы уже пользуетесь атрибутами для пометок на ваших элементах, вот вам совет. Вы можете создать кастомную команду, которая сможет выбирать ваш элемент по, скажем, атрибуту data-cy:

Cypress.Commands.add('getById', (input) => {
cy
.get(`[data-cy=${input}]`)
})

Затем ее можно использовать в тесте:

cy
.getById('indigo')

Выбор элементов может, конечно, быть болезненным делом, когда вы только начинаете и не знаете, что есть что. Надеюсь, это руководство поможет вам путешествовать по DOM вашего приложения. Если вы уже профи, поделитесь ссылкой с друзьями. Возможно, они все еще страдают!

Обсудить в форуме