Developer Snippet Diary

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

<h3>Sign up</h3>
<label>
  <input type="checkbox" /> Subscribe
</label>
<br/>
<button>Submit</button>
await expect(page.getByRole('heading', { name: 'Sign up' })).toBeVisible();
await page.getByRole('checkbox', { name: 'Subscribe' }).check();
await page.getByRole('button', { name: /submit/i }).click();

 

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>
<button>Submit</button>
<button aria-label="Submit"></button>
exact Match exact text (no partial match), ??? Matches: Submit
??? Not match: Submit Form
{ name: 'Submit', exact: true }
level

Specifies heading level (h1 → 1, h2 → 2)

Only level works for headings,
page.getByRole('heading', { name: 'Dashboard' })

await page.getByRole('heading', { level: 1 })

It finds h1 only not h2

<h1>Welcome</h1>
checked

Filters checked checkbox/radio

page.getByRole('checkbox', { checked: true })
selected

For selected option in dropdown/list

page.getByRole('option', { selected: true })
disabled

Finds disabled elements

page.getByRole('button', { disabled: true })


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
page.locator("button")
page.locator("#login")
page.locator(".card")
page.locator("div > span")
page.locator("input[type='text']")
page.locator("text=Submit")
page.locator("//button[text()='Submit']")

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()

 

Posted by: R GONDAL
Email: rizikmw@gmail.com