Selector Playground
A comprehensive test surface for Playwright & other automation frameworks. Every element is annotated with the recommended selector strategy.
IDs & Classes CSS
Unique IDs and reusable class selectors — the most common Playwright targets.
Unique ID
#btn-unique-idlocator('#btn-unique-id')
Class selector
.btn-example-classlocator('.btn-example-class')
Multiple classes
status-active.badge.badge-green.badge.status-active
Attribute Selectors CSS
Target elements by any HTML attribute value.
[name='username'][placeholder*='email'][type='password'][href*='playwright'][disabled][readonly]
ARIA & Roles Accessibility
Playwright's getByRole() is the recommended strategy — resilient and accessible-first.
getByRole('button', { name: 'Submit form' })
getByRole('searchbox', { name: 'Search products' })
getByLabel('First name')
Status widget
getByRole('button', { name: /submit/i })getByRole('alert')[aria-label='...'][aria-current='page']
data-testid Best Practice
The safest selector strategy: add data-testid (or any custom attribute) to elements.
Use getByTestId() in Playwright.
getByTestId('login-button')
getByTestId('search-input')
getByTestId('user-greeting')
Custom data attributes
[data-cy='submit-btn'][data-qa='cancel-btn'][data-automation-id='save-btn']locator('[data-testid]')— any with testid
CSS Selectors Advanced
Pseudo-classes, combinators, and structural selectors.
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
#css-demo-list li:first-child→ Item 1#css-demo-list li:last-child→ Item 5#css-demo-list li:nth-child(3)→ Item 3#css-demo-list li:nth-child(odd)→ 1,3,5#css-demo-list li:nth-child(even)→ 2,4
button + input— adjacent siblingdiv > p— direct childform ~ p— general siblinginput:not([disabled])— negationa[href^='https']— starts withp:has(> strong)— has child
XPath Hints XPath
XPath selectors for cases where CSS can't reach (text content, axes).
Exact text: Hello Playwright
Contains text: Automation is fun
Sibling of:
//span[text()='Hello Playwright']//em[contains(text(),'fun')]//button[@id='xpath-btn']//*[@class and contains(@class,'btn')]//button/following-sibling::input//label[text()='Email']/following::input[1]xpath=//p[@id='xpath-target-1']
Text & Input Fields Forms
All standard input types for fill(), type(), clear().
Checkboxes & Radio Buttons Forms
Use check(), uncheck(), isChecked().
Checkboxes
Radio Buttons
Dropdowns & Select Forms
Use selectOption() by value, label, or index.
File Upload & Range Forms
Use setInputFiles() for uploads, fill() for range inputs.
#7c6af7
Form Validation Forms
Required fields, patterns, min/max — use evaluate() to check validity.
Buttons Click
All button variants for click(), dblclick(), rightClick().
Modals & Alerts Dialog
Browser dialogs: page.on('dialog', d => d.accept()). Custom modals: locator.
Tabs Navigation
Click tabs with getByRole('tab') then assert panel visibility.
This is the Overview tab panel. Visible when tab 1 is active.
getByRole('tab', { name: 'Overview' }).click()
This is the Details tab panel. Hidden until clicked.
expect(getByTestId('tabpanel-details')).toBeVisible()
This is the Reviews tab panel with some content.
Accordion Toggle
Expand/collapse with click; assert visibility of body.
data-testid decouples tests from implementation details (CSS classes, DOM structure), making them resilient to UI refactors.
Hover & Tooltip Mouse
Use hover(). Tooltips appear on :hover.
Dropdown Menu Navigation
Hover/click to reveal; use locator to select items.
Tables Data
Sortable table. Use locator('table'), getByRole('row'), getByRole('cell').
| ID | Name | Role | Status | Actions |
|---|---|---|---|---|
| 001 | Alice Johnson | SDET | Active | |
| 002 | Bob Smith | QA Lead | Pending | |
| 003 | Carol White | Developer | Inactive | |
| 004 | David Lee | DevOps | Remote | |
| 005 | Eve Martinez | SDET | Active |
Pagination Navigation
Use getByRole('button') or data-testid to navigate pages.
Badges, States & Indicators UI
Assert text content, class presence, and visibility of state indicators.
Dynamic Content Async
Elements that appear, disappear, or change after user actions or timers.
Use waitForSelector(), waitFor(), expect().toBeVisible().
Appears after delay (2s)
Updating counter (every 1s)
Toggle visibility
I am the toggled text element.
Add / Remove list items
Loading States Async
Spinners, skeleton screens, and loading placeholders. Use waitForSelector with state hidden/visible.
Lazy / Infinite Load Scroll
Items load on button click (simulating scroll trigger). Use waitForSelector.
Multi-step Form Workflow
Step through a wizard; assert active step and visible fields.
✓ All steps complete! Ready to submit.
Progress Bar State
Assert progress value with getAttribute('aria-valuenow').
Drag & Drop Mouse
Use dragTo() or Playwright's mouse API for drag interactions.
Draggable items
Drop zone
Shadow DOM Advanced
Playwright auto-pierces shadow DOM. Use locator() as normal — no special handling needed.
Shadow DOM loading…
- Playwright auto-pierces shadow roots for most selectors
locator('#shadow-input')works inside shadow DOM- CSS selectors:
locator('my-component >> input')
iFrame Advanced
Use page.frameLocator('iframe') to interact inside frames.
page.frameLocator('#embedded-frame').locator('#iframe-input').fill('text')page.frameLocator('[data-testid="embedded-frame"]').getByTestId('iframe-button').click()
Keyboard Input Keys
Test press(), type(), key combos, and special keys.
press('Tab')press('Enter')press('Control+A')press('Escape')press('ArrowDown')keyboard.type('Hello World')
Nested Lists & Trees Hierarchy
Complex DOM traversal; useful for menu trees and nested structures.
- QA Tools
- Playwright
- Selenium
- Java
- Python
- Cypress
- Languages
- TypeScript
- Java
- Python
[data-testid='list-item-playwright']ul > li:first-child > ul > li//li[@data-testid='list-item-selenium']/ul/ligetByTestId('nested-list').locator('li')→ all items.filter({ hasText: 'Java' })