Часть 1. Ответы
- role → label/placeholder/text → test_id → CSS/XPath (крайний случай).
- «Ленивый» локатор ищет элемент заново при каждом действии, поэтому не «протухает» после перерисовки DOM; снимок из
find_elementустаревает. - Strict mode violation — локатор нашёл >1 элемента. Устранение: уточнить (
name=,.filter(),.nth()). get_by_textищет элемент по тексту;.filter(has_text=...)сужает уже найденный набор (например, нужныйlistitem).expect(locator).to_have_count(n).
Часть 2. Локаторы — эталон
page.get_by_role("button", name="Оформить заказ")
page.get_by_label("Электронная почта")
page.get_by_role("link", name="Личный кабинет")
page.get_by_label("Запомнить меня")
page.locator(".product").nth(2) # третий (индекс с 0)
Часть 3 и 4. Форма и список — эталон
# test_saucedemo.py
from playwright.sync_api import Page, expect
def test_login_and_cart(page: Page):
page.goto("https://www.saucedemo.com/")
page.get_by_placeholder("Username").fill("standard_user")
page.get_by_placeholder("Password").fill("secret_sauce")
page.get_by_role("button", name="Login").click()
expect(page.get_by_text("Products")).to_be_visible()
expect(page).to_have_url("https://www.saucedemo.com/inventory.html")
items = page.locator(".inventory_item")
expect(items).to_have_count(6)
items.filter(has_text="Sauce Labs Backpack") \
.get_by_role("button", name="Add to cart").click()
expect(page.locator(".shopping_cart_badge")).to_have_text("1")
⚠️ Классы/тестиды реального сайта могут отличаться — проверяйте через инспектор/codegen. Здесь важен подход.