Схемы, примеры, и варианты кода. В колонке Selenide даны несколько наиболее удобных способов.
| Rule | Schema | Example | Comment | Selenide (варианты) | Selenium | Playwright (python) |
|---|---|---|---|---|---|---|
| tag & attribute | //tag[@attribute="value"] |
//input[@placeholder="Username"] |
Находит элемент по тэгу и атрибуту |
$(byXpath("//input[@placeholder='Username']"))
|
driver.findElement(By.xpath("//input[@placeholder='Username']"))
|
page.locator("xpath=//input[@placeholder='Username']")page.get_by_placeholder("Username")
|
| text() | //tag[text()="value"] |
//button[text()="Login"] |
Полное совпадение прямого текстового узла элемента. Не
сматчит текст внутри вложенных тегов
(<button><span>Login</span></button>).
Для устойчивости к пробелам и вложениям используют
normalize-space(.)="…" или просто
.="…".
|
$(byText("Login"))$$("button").findBy(text("Login"))$(byXpath("//button[text()='Login']"))
|
driver.findElement(By.xpath("//button[text()='Login']"))
|
page.get_by_text("Login", exact=True)page.locator("xpath=//button[text()='Login']")
|
| contains() (text) | //tag[contains(text(),"value")] |
//div[contains(text(),"Error")] |
Частичное совпадение прямого текстового узла. Текст
внутри вложенных тегов так не находится; для «всего текста
элемента» — contains(., "Error") или
contains(normalize-space(.), "Error").
|
$(withText("Error"))Генерирует примерно такой XPath: .//*[contains(normalize-space(.),'Error')] $(byXpath("//div[contains(text(),'Error')]"))
|
driver.findElement(By.xpath("//div[contains(text(),'Error')]"))
|
page.get_by_text("Error")page.locator("xpath=//div[contains(text(),'Error')]")
|
| contains() (attr) | //tag[contains(@attribute,"value")] |
//input[contains(@placeholder,"Usern")] |
Частичное совпадение значения атрибута |
$(byXpath("//input[contains(@placeholder,'Usern')]"))
|
driver.findElement(By.xpath("//input[contains(@placeholder,'Usern')]"))
|
page.locator("xpath=//input[contains(@placeholder,'Usern')]")
|
| multiple attributes | //tag[rule1][rule2] |
//input[@type="text"][@name="login"] |
Несколько условий |
$("input[type='text'][name='login']")$(byCssSelector("input[type='text'][name='login']"))$(byXpath("//input[@type='text'][@name='login']"))
|
driver.findElement(By.xpath("//input[@type='text'][@name='login']"))
|
page.locator("input[type='text'][name='login']")page.locator("xpath=//input[@type='text'][@name='login']")
|
| moving through the tree | //parent/child |
//div/span |
Прямой потомок (один уровень вниз). В XPath
/ — строго дочерний шаг; для «любой глубины»
нужно //div//span. CSS-эквивалент —
div > span, а не div span.
|
$("div > span")$(byXpath("//div/span"))
|
driver.findElement(By.xpath("//div/span")) |
page.locator("div > span")page.locator("xpath=//div/span")
|
| not() | //tag[not(contains(@attr,"v"))] |
//input[not(contains(@type,"hidden"))] |
Исключение по условию |
$(byXpath("//input[not(contains(@type,'hidden'))]"))
|
driver.findElement(By.xpath("//input[not(contains(@type,'hidden'))]"))
|
page.locator("xpath=//input[not(contains(@type,'hidden'))]")
|
| indexing | (//tag[@attr="v"])[N] |
(//input[@type="text"])[2] |
N‑й элемент в выборке. Нумерация в XPath начинается с
1; в Selenide-коллекциях
$$().get(i) — с 0, поэтому
get(1) ≈ (…)[2].
|
$$("input[type='text']").get(1)$(byXpath("(//input[@type='text'])[2]"))
|
driver.findElement(By.xpath("(//input[@type='text'])[2]"))
|
page.locator("input[type='text']").nth(1)page.locator("xpath=(//input[@type='text'])[2]")
|
| parent | //tag/.. |
//input/.. |
Переход к родителю | $(byXpath("//input/..")) |
driver.findElement(By.xpath("//input/..")) |
page.locator("xpath=//input/..") |
| following-sibling | //tag/following-sibling::tag2 |
//label/following-sibling::input |
Все подходящие среди следующих братьев на том же уровне. Ось
following-sibling::… сама по себе значит: «все подходящие tag2 среди следующих братьев», а не «первый попавшийся».
|
$(byXpath("//label/following-sibling::input")) |
driver.findElement(By.xpath("//label/following-sibling::input"))
|
page.locator("xpath=//label/following-sibling::input")
|
| preceding-sibling | //tag/preceding-sibling::tag2 |
//input/preceding-sibling::label |
Все подходящие среди предыдущих братьев на том же уровне.
Ось preceding-sibling::… сама по себе значит:
«все подходящие tag2 среди предыдущих братьев», а не
«ближайший слева».
|
$(byXpath("//input/preceding-sibling::label")) |
driver.findElement(By.xpath("//input/preceding-sibling::label"))
|
page.locator("xpath=//input/preceding-sibling::label")
|
| ancestor | //tag/ancestor::X |
//span/ancestor::form |
Все подходящие предки выше по дереву (а не «один любой»).
Для ближайшего предка — ancestor::form[1].
|
$(byXpath("//span/ancestor::form")) |
driver.findElement(By.xpath("//span/ancestor::form"))
|
page.locator("xpath=//span/ancestor::form")
|
| Rule | Schema | Example | Comment | Selenide (варианты) | Selenium | Playwright (python) |
|---|---|---|---|---|---|---|
| tag & attribute | tag[attribute="value"] |
input[aria-label="Search"] |
По тегу и точному значению атрибута |
$("input[aria-label='Search']")$(byAttribute("aria-label","Search"))$(byCssSelector("input[aria-label='Search']"))
|
driver.findElement(By.cssSelector("input[aria-label='Search']"))
|
page.locator("input[aria-label='Search']")
|
| id | #id |
#loginBtn |
По id |
$("#loginBtn")$(byId("loginBtn"))
|
driver.findElement(By.id("loginBtn")) |
page.locator("#loginBtn")page.locator("[id='loginBtn']")
|
| class name | .className |
.btn-primary |
По классу |
$(".btn-primary")$(byClassName("btn-primary"))
|
driver.findElement(By.className("btn-primary"))
|
page.locator(".btn-primary") |
| multiple class names | .class1.class2 |
.btn.large |
Два класса одновременно |
$(".btn.large")$(byCssSelector(".btn.large"))
|
driver.findElement(By.cssSelector(".btn.large"))
|
page.locator(".btn.large") |
| attribute *= | [attribute*="value"] |
input[placeholder*="user"] |
Атрибут содержит подстроку.
byAttribute(name, value) сюда не подходит — он
генерирует точное совпадение
[name="value"].
|
$("input[placeholder*='user']")$(byCssSelector("input[placeholder*='user']"))
|
driver.findElement(By.cssSelector("input[placeholder*='user']"))
|
page.locator("input[placeholder*='user']")
|
| attribute ^= | [attribute^="value"] |
input[placeholder^="user"] |
Атрибут начинается с |
$("input[placeholder^='user']")$(byCssSelector("input[placeholder^='user']"))
|
driver.findElement(By.cssSelector("input[placeholder^='user']"))
|
page.locator("input[placeholder^='user']")
|
| attribute $= | [attr$="value"] |
img[src$=".png"] |
Атрибут заканчивается на |
$("img[src$='.png']")$(byCssSelector("img[src$='.png']"))
|
driver.findElement(By.cssSelector("img[src$='.png']"))
|
page.locator("img[src$='.png']") |
| name / link text (полезно знать) | a:contains(text) - (нет в чистом CSS) |
Ссылки по тексту |
В CSS нет поиска по тексту - используем API |
$(byLinkText("Home"))$(byPartialLinkText("Hom"))
|
driver.findElement(By.linkText("Home"))driver.findElement(By.partialLinkText("Hom"))
|
page.get_by_role("link", name="Home")page.locator("a").filter(has_text="Hom")
|
Импорты (Selenide):
import static com.codeborne.selenide.Selenide.*;,
import static com.codeborne.selenide.Selectors.*;,
import static com.codeborne.selenide.Condition.*;
Playwright (Python): в примерах используется объект
page из playwright.sync_api (например после
browser.new_page()).