Locators | Find elements and get there data
Locators are the central piece of Playwright's auto-waiting and retry-ability. https://playwright.dev/python/docs/locators
FIND ELEMENTS
1. FIND BY ROLE
Locate by role only use when you know clear roles ie don't use it for div finding
When locating by role, you should usually pass the accessible name as well, so that the locator pinpoints the exact element.
page.getByRole(role{string}, options{object})
ie
|
|
| Role | ie | Role | ie |
| button | Clickable button | combobox | Dropdown |
| link | <a> link | list | <ul> / <ol> |
| heading | <h1> to <h6> | listitem | <li> |
| textbox | Input field | dialog | Modal |
| checkbox | Checkbox | img | Image |
| radio | Radio button | table | Table |
| row | Table row | cell | Table cell |
OPTIONS
| name | Text visible to users Visible text aria-label aria-labelledby associated <label> |
|
| exact | Match exact text (no partial match), ??? Matches: Submit ??? Not match: Submit Form |
|
| level |
Specifies heading level (h1 → 1, h2 → 2) Only level works for headings, |
It finds h1 only not h2
|
| checked |
Filters checked checkbox/radio |
|
| selected |
For selected option in dropdown/list |
|
| disabled |
Finds disabled elements |
|
EXAMPLE:
heading → role , level: 1 → <h1> ,checking text = Welcome
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Welcome');
Buttons:
page.getByRole('button', { name: 'Login' })
page.getByRole('button', { name: /login/i }) // regex (case insensitive)
page.getByRole('button', { name: 'Save', exact: true })
Inputs:
page.getByRole('textbox', { name: 'Email' })
page.getByRole('textbox', { name: 'Search' })
page.getByRole('textbox').nth(0) // if no label
1. FIND BY LOCATOR
It creates a Locator object that targets elements using a selector.
locator = page.locator("CSS selector, text selector, XPath")
| CSS LOCATOR | TEXT | XPATH |
|
|
|
Advance locators :
page.locator("div:has-text('Hello')")
page.locator("div:has(button)")
page.locator("button:visible")
page.locator("button").nth(0)
Locator is LAZY (VERY IMPORTANT)
locator = page.locator("button") #??? No DOM query yet, ??? No error even if element doesn’t exist
locator.click() #Only runs when
Locator is Strict Mode ??? Error if multiple elements
page.locator("button").click() #WRONG
page.locator("button").first.click()
page.locator("button").nth(1).click()
Chaining Locators (VERY POWERFUL) means, Find all div => Inside them find button
page.locator("div").locator("button")
Multiple Elements Handling
locator.count()
locator.nth(0)
locator.first
locator.last
profile_link = question_box.locator('a[href*="/profile/"]').first
await profile_link.wait_for(state="visible", timeout=3000) #MAX WAIT
Locator Actions:
locator.click()
locator.fill("text")
locator.type("text")
locator.hover()
locator.press("Enter")
locator.check()
locator.uncheck()
locator.wait_for(state="visible") #attached , detached , visible , hidden
Find single element:
locater = page.get_by_placeholder("e.g Cheetos")
locater = page.get_by_text("Bitcoin in Islam") # working for all page text any where, or inside any element
Find Multiple Elements:
articles = page.get_by_role("article") # all articles
for i in range(articles.count()):
article = articles.nth(i)
text = article.text_content()[:100] # First 100 chars for brevity
print(f"Article {i}: {text}...")
By Place Holder:
locater = page.get_by_placeholder("e.g Cheetos")
Find element by text:
# working for all page text any where, or inside any element
locater = page.get_by_text("Bitcoin in Islam")
Find By alt text:
page.get_by_alt_text("My image 1")
Locate By CSS/xpath:
page.locator("css=button").click()
page.locator("xpath=//button").click()
page.locator(
"#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input"
).click()
If multiple items, First find it and then use it Filter
page.get_by_role("listitem").filter(has_text="Product 2").get_by_role(
"button", name="Add to cart"
).click()
Wait for locaters
order_sent = page.locator("#order-sent")
order_sent.wait_for() #"attached" present in DOM| "detached" not present| "visible" (default) | "hidden" (optional)
Find Element with multiple conditions
button = page.get_by_role("button").and_(page.getByTitle("Subscribe")) #Locator,
# 1. profile link (VERY specific)
#FIND
profile_link = question_box.locator('a[href*="/profile/"]').first
#ASSERT
await profile_link.wait_for(state="visible", timeout=3000)
#get attribute
profile_url = await profile_link.get_attribute('href')
print("Profile URL:", profile_url)
#get text of element
profile_name = await profile_name_el.inner_text()
await profile_link.click()
Play with Finded Elements
For Multiple Items loop
for row in page.get_by_role("listitem").all():
print(row.text_content())
Inner Text : # Returns an array of node.innerText list values
texts = page.get_by_role("link").all_inner_texts()
All Text Contents: #Returns an array of node.textContent
texts = page.get_by_role("link").all_text_contents()
Get Attribute:
locator.get_attribute(name)
Highlight the element: #################
page.get_by_role("button").highlight()
Inner Html
locator.inner_html()
Only Visible text: return string
locator.inner_text()
Outer HTML
outer_html = su.evaluate("element => element.outerHTML")
First Element find
banana = page.get_by_role("listitem").nth(0)
banana = page.get_by_role("listitem").last
apple = page.get_by_role("listitem").first
Screenshoot
page.get_by_role("link").screenshot()
Text Of Element
locator.text_content()