В предыдущей статье в основном объяснялись теоретические базовые знания о некоторых наиболее часто используемых методах позиционирования с использованием Playwright для позиционирования элементов в нашей повседневной работе, а также о том, при каких обстоятельствах их рекомендуется использовать. Сегодня в этой статье мы объясним и поделимся некоторыми позициями, которые редко используются или редко встречаются в повседневной жизни, но мы должны знать об этом, когда сталкиваемся с этим. Как говорится: не паникуйте, когда у вас в руке еда.
При веб-автоматизации некоторые элементы находятся под теневым корневым узлом, что делает невозможным их обнаружение с помощью XPath в драматурге.
Тег теневого корня, показанный выше, на самом деле является теневым DOM. Что же такое теневой DOM?
Это технология инкапсуляции страниц во внешнем интерфейсе. ShadowDOM можно рассматривать как «DOM в DOM» (можно рассматривать как скрытый DOM).
Это независимое дерево DOM со своими элементами и стилями, полностью изолированное от исходного документа DOM.
ShadowDOM должен быть прикреплен к элементу HTML для хранения элементаshadowDOM. Мы можем назвать его хост-элементом. В HTML5 существует множество стилей тегов, реализованных через ShadowDOM.
Например: поле выбора даты, тег воспроизведения аудио и тег воспроизведения видео имеют свои собственные стили (хотя этот вид инкапсуляции хорош для внешней разработки, наши тестировщики столкнутся с некоторыми проблемами при автоматическом веб-рендеринге, метка ShadowDOM; в не может быть найден).
По умолчанию все локаторы в Playwright используют элементы из Shadow DOM. Исключения:
Например: следующие образцы и пользовательские веб-компоненты:
<x-details role=button aria-expanded=true aria-controls=inner-details>
<div>Title</div>
#shadow-root
<div id=inner-details>Details</div>
</x-details>
Вы можете расположить его так же, как если бы теневого корня вообще не существовало.
Чтобы нажать :<div>Details</div>
page.get_by_text("Details").click()
Чтобы нажать :<x-details>
page.locator("x-details", has_text="Details" ).click()
Обязательно укажите текст «Подробнее».,Пожалуйста, сделайте следующее:<x-details>
expect(page.locator("x-details")).to_contain_text("Details")
Например, следующая структура DOM, в которой мы хотим нажать кнопку «Купить» на второй карточке продукта. У нас есть несколько вариантов фильтрации локаторов, чтобы получить правильный локатор.
Локаторы можно фильтровать по тексту с помощью метода locator.filter(). Он будет искать определенную строку где-то внутри элемента, возможно, в элементе-потомке, без учета регистра. Вы также можете передать регулярное выражение.
1. Используйте текст
page.get_by_role("listitem").filter(has_text="Product 2").get_by_role(
"button", name="Add to cart"
).click()
2. Используйте регулярные выражения
page.get_by_role("listitem").filter(has_text=re.compile("Product 2")).get_by_role(
"button", name="Add to cart"
).click()
3. Фильтровать по тексту
# 5 in-stock items
expect(page.get_by_role("listitem").filter(has_not_text="Out of stock")).to_have_count(5)
Локаторы поддерживают возможность выбирать только элементы с потомками или без них, которые соответствуют другим локаторам. Таким образом, вы можете фильтровать по любому другому локатору, например locator.get_by_role(), locator.get_by_test_id(), locator.get_by_text() и т. д.
1. Используйте подразделы
page.get_by_role("listitem").filter(
has=page.get_by_role("heading", name="Product 2")
).get_by_role("button", name="Add to cart").click()
2. Используйте утверждения карточек товаров, чтобы убедиться, что существует только один
expect(
page.get_by_role("listitem").filter(
has=page.get_by_role("heading", name="Product 2")
)
).to_have_count(1)
3. Фильтровать по элементам, у которых нет подходящих внутренних элементов.
expect(
page.get_by_role("listitem").filter(
has_not=page.get_by_role("heading", name="Product 2")
)
).to_have_count(1)
Постучите по доске! ! ! ! Примечание. Внутренние локаторы соответствуют внешнему локатору, а не корню документа.
Метод locator.and_() сужает область действия существующего локатора, сопоставляя другие локаторы. Например, вы можете объединить page.get_by_role() и page.get_by_title() для сопоставления по роли и заголовку.
button = page.get_by_role("button").and_(page.getByTitle("Subscribe"))
Вы можете объединить методы, создающие локаторы (например, page.get_by_text() или locator.get_by_role()), чтобы сузить поиск до определенной части страницы.
В этом примере,Мы сначалапроходитьопределить свою роль:listitem чтобы создать файл с именем product локатор. Затем фильтруем по тексту. Мы можем снова использовать локатор продукта, чтобы получить роль кнопки, и щелкнуть ее, а затем использовать утверждение, чтобы убедиться, что существует только одна кнопка с текстом «Продукт». 2” продукт.
product = page.get_by_role("listitem").filter(has_text="Product 2")
product.get_by_role("button", name="Add to cart").click()
Вы также можете связать два локатора вместе, например, чтобы найти кнопку «Сохранить» в определенном диалоговом окне:
save_button = page.get_by_role("button", name="Save")
# ...
dialog = page.get_by_test_id("settings-dialog")
dialog.locator(save_button).click()
Локаторы могут использоваться для подсчета элементов в списке. Например: посмотрите на структуру DOM
Используйте утверждение подсчета, чтобы убедиться, что список содержит 3 элемента.
expect(page.get_by_role("listitem")).to_have_count(3)
Локаторы могут быть утверждены для поиска всего текста в списке. Используйте ожидаемый(локатор).to_have_text(), чтобы убедиться, что список содержит текст «яблоко», «банан» и «апельсин».
expect(page.get_by_role("listitem")).to_have_text(["apple", "banana", "orange"])
Существует множество способов найти определенные элементы в списке.
Используйте метод page.get_by_text(), чтобы найти элемент в списке по текстовому содержимому и щелкнуть по нему.
Найдите элемент по его текстовому содержимому и нажмите на него.
page.get_by_text("orange").click()
Используйте locator.filter() для поиска определенных элементов в списке. Найдите элемент по роли «Элемент списка», отфильтруйте его по тексту «Оранжевый» и щелкните по нему.
page.get_by_role("listitem").filter(has_text="orange").click()
Используйте метод page.get_by_test_id(), чтобы найти элемент в списке. Если у вас еще нет идентификатора теста, возможно, вам придется изменить HTML-код и добавить идентификатор теста.
Найдите предмет по идентификатору теста «оранжевый» и нажмите на него.
page.get_by_test_id("orange").click()
Если у вас есть список идентичных элементов и отличить их можно только по порядку, вы можете выбрать конкретный элемент из списка с помощью locator.first, locator.last или locator.nth().
banana = page.get_by_role("listitem").nth(1)
Однако используйте этот метод с осторожностью. Часто страница может измениться, и локатор будет указывать на совершенно другой элемент, чем ожидалось. Вместо этого попытайтесь придумать уникальный локатор, отвечающий строгим критериям.
Если у вас есть элементы с различным сходством, вы можете использовать метод locator.filter() для выбора правильного элемента. Вы также можете связать несколько фильтров, чтобы сузить выбор.
Чтобы сделать скриншот строк с «Мэри» и «Попрощайся»:
row_locator = page.get_by_role("listitem")
row_locator
.filter(has_text="Mary")
.filter(has=page.get_by_role("button", name="Say goodbye"))
.screenshot(path="screenshot.png")
Итерация элементов
for row in page.get_by_role("listitem").all():
print(row.text_content())
Выполните итерацию, используя обычный цикл for:
rows = page.get_by_role("listitem")
count = rows.count()
for i in range(count):
print(rows.nth(i).text_content())
Код в locator.evaluate_all() выполняется на странице, где вы можете вызвать любой API DOM.
rows = page.get_by_role("listitem")
texts = rows.evaluate_all("list => list.map(element => element.textContent)")
Локатор очень строгий. Это означает, что все операции с локатором, которые подразумевают какой-либо целевой элемент DOM, будут вызывать исключение, если совпадают несколько элементов. Например, если в DOM имеется несколько кнопок, выполняется следующий вызов:
page.get_by_role("button").click()
С другой стороны, Playwright понимает, когда следует выполнять операции с несколькими элементами, поэтому следующий вызов работает нормально, когда локатор разрешается для нескольких элементов.
page.get_by_role("button").count()
Вы можете явно отказаться от проверки строгости, сообщив Playwright, какой элемент использовать, когда несколько элементов совпадают, с помощью locator.first, locator.last и locator.nth(). Эти методы не рекомендуются, поскольку Playwright может щелкнуть ненужные вам элементы при изменении страницы. Вместо этого следуйте приведенным выше рекомендациям, чтобы создать локатор, который однозначно идентифицирует целевой элемент.
Для менее часто используемых локаторов,Пожалуйста, проверьте официальный сайтДругие локаторыгид。из-за ограничений по времени,Брат Хун не будет здесь представлять и объяснять это. Ладно, уже поздно,Давайте сегодня поделимся методом позиционирования элемента! ! ! Только для справки,Спасибо за ваше терпеливое чтение.