Что такое локатор
В Selenium find_element сразу возвращает элемент — «снимок» на момент вызова. В Playwright page.get_by_role(...) возвращает локатор — описание того, как найти элемент. Реальный поиск происходит в момент действия (click, fill) или проверки (expect). Поэтому локатор не «протухает»: если страница перерисовалась, элемент будет найден заново.
Встроенные локаторы (рекомендуемые)
Playwright советует искать элементы так, как их видит пользователь — это устойчивее к изменениям вёрстки.
# По роли (кнопки, ссылки, поля) — самый рекомендуемый
page.get_by_role("button", name="Войти")
page.get_by_role("link", name="Документация")
page.get_by_role("checkbox", name="Согласен")
# По связанному label (поля форм)
page.get_by_label("Пароль")
# По placeholder
page.get_by_placeholder("name@example.com")
# По видимому тексту
page.get_by_text("Заказ оформлен")
page.get_by_text("Войти", exact=True) # точное совпадение
# По alt (картинки) и title
page.get_by_alt_text("Логотип")
page.get_by_title("Количество задач")
# По data-testid (когда роли/текста недостаточно)
page.get_by_test_id("submit-btn")
.btn.btn-primary > span.
CSS и XPath — крайний случай
page.locator("css=button.primary")
page.locator(".product-card") # CSS определяется автоматически
page.locator("//button[@type='submit']") # XPath
Их используют, когда нет ни роли, ни лейбла, ни стабильного текста.
Фильтрация и сцепление
# Сцепление: внутри найденного элемента ищем дальше
page.get_by_role("listitem").filter(has_text="Молоко").get_by_role("button").click()
# По индексу
page.get_by_role("listitem").nth(1)
page.get_by_role("listitem").first
page.get_by_role("listitem").last
# has / has_not_text
page.get_by_role("listitem").filter(has_not_text="Нет в наличии")
Действия и actionability
Перед действием Playwright проверяет, что элемент готов: существует, видим, стабилен (не двигается), включён, не перекрыт. Эти проверки повторяются до таймаута — отсюда «авто-ожидание».
| Действие | Что делает |
|---|---|
click() | Клик |
fill("текст") | Очистить и ввести в поле |
check() / uncheck() | Чекбокс/радио |
select_option("value") | Выбор в <select> |
press("Enter") | Нажатие клавиши |
hover() | Навести курсор |
Web-first проверки expect()
from playwright.sync_api import expect
expect(page.get_by_text("Готово")).to_be_visible()
expect(page.locator(".count")).to_have_text("3")
expect(page.get_by_role("listitem")).to_have_count(5)
expect(page.get_by_label("Email")).to_have_value("a@b.com")
Каждая такая проверка повторяется до таймаута, пока условие не станет истинным. Это убирает «мигающие» падения.
Strict mode
Если локатор находит несколько элементов, а вы вызываете действие на одном — Playwright бросает ошибку strict mode violation. Это намеренно: тест должен однозначно указывать на элемент. Уточните локатор (name=, .filter(), .nth()).
expect и опций локаторов — в официальной документации по assertions.