Skip to main content

QA Bash Learning

Element Playground.

40+ live elements to practice locators on — each with a ranked strategy list. Test your own selector against the real page with the bar at the bottom.

Every card's icon and copy button carry data-qb-chrome — exclude them with a selector like button:not([data-qb-chrome]) if you're testing something broad in the bar below.

Text Inputs

Standard Text Input

Easy

Password Input

Easy

Email Input — ARIA Label Only

Medium

No id, name, or data-testid on this one — ARIA is the only strong option. This is intentional: plenty of real forms look exactly like this.

Disabled Number Input

Easy

Disabled elements are still locatable — most frameworks require an explicit enabled-state check before you can interact with them.

Readonly Search Input

Medium

Zero-Attribute Textarea

Hard

No id, name, aria-label, or test id at all. In a real app, flag this to a developer — but you still need to test it today, so placeholder is the least-bad option.

Selection Controls

Single Checkbox

Easy

Checkbox Group

Medium

Radio Group

Easy

Native Select — Single

Easy

Native Select — Multiple

Medium

Custom JS Dropdown

Hard

This isn't a native <select> — it won't respond to selectOption(). Click the trigger, then click the option in the opened listbox.

Toggle Switch

Easy

aria-checked flips when toggled — don't hardcode the current state into your selector.

Range Slider

Medium

Dynamic & Timing Challenges

Appears After Delay

Medium

Waiting… (appears at 3s)

Doesn't exist in the DOM for the first 3 seconds after this section mounts — use an explicit wait/assertion with a timeout, not an immediate query.

Countdown-Enabled Button

Medium

Exists immediately but stays disabled for 5 seconds — wait for the disabled attribute to clear, don't just wait for the element to exist.

Auto-Refreshing Counter

Hard
0

Text content changes every 2 seconds — don't assert exact text, assert a pattern or that the value changed between two reads.

Regenerating-ID Element

Expert

current id: field-

The classic dynamic-ID trap — common in frameworks like Angular Material or MUI that auto-generate IDs. Always check whether an ID looks suspicious (long random suffix) before trusting it.

Typeahead / Autocomplete

Hard

The options list doesn't exist until you type — query it after triggering input, not before.

Infinite Scroll List

Hard
  • Result #1
  • Result #2
  • Result #3
  • Result #4
  • Result #5
  • Result #6

New items only mount once you scroll near the bottom — for items beyond the initial batch, scroll the container into view first, then re-query.

Overlays

Modal Dialog

Medium

Focus is trapped inside while open — Tab won't reach elements behind it. Close via Cancel/Confirm or Escape; there's no backdrop-click-to-close here.

Toast (Auto-Dismiss)

Medium

Auto-dismisses after 3 seconds — assert on it immediately after triggering, don't add a long wait first or you'll query after it's gone.

Hover-Only Tooltip

Medium

The tooltip content is only in the DOM while the trigger is hovered or focused — hover() or focus() the trigger before asserting it's visible.

Right-Click Context Menu

Hard
Right-click here

Triggered by the contextmenu event, not a normal click — most frameworks need an explicit right-click/contextmenu action, not click().

Cookie Consent Banner

Medium

Dismissed.

State-dependent — once dismissed it stays hidden (stored in localStorage) until you hit Reset. Good practice for testing first-visit vs. returning-visitor scenarios.

Structural & Frames

Same-Origin Iframe

Medium

You must switch into the iframe's context before interacting with elements inside it (Playwright's frameLocator(), Selenium's driver.switchTo().frame()).

Nested Iframe

Hard

Two frame switches deep — switch into the outer frame, then into the inner one, before the button becomes reachable.

Shadow DOM Component

Expert

Real shadow DOM (mode: open). Playwright's locator() pierces shadow roots automatically; plain document.querySelectorAll/XPath cannot — try the Selector Tester below on a selector for the button inside and watch it return 0 matches.

Sortable + Paginated Table

Hard
Name ↕Role
Carol WhiteQA Lead
Bob SmithSDET
Alice JohnsonAutomation Engineer
Page 1 of 3

Row order changes when sorted and the row set changes per page — don't hardcode 'row 3' as an identifier; locate by the cell's actual content instead.

HTML5 Drag and Drop

Hard
  • Task 1
  • Task 2
  • Task 3
  • Drop here

    Native HTML5 drag-and-drop doesn't respond to simple mouse-down/move/up sequences in most tools — use Playwright's dragTo() or Selenium's Actions dragAndDrop(), built specifically for this.

    File Upload

    Medium

    File inputs can't be 'typed' into for security reasons — use setInputFiles() (Playwright) or sendKeys(path) (Selenium) directly on the <input type="file">, never simulate a click-then-type.

    Advanced & Ambiguous

    5 Identical Buttons

    Expert

    All five buttons are byte-for-byte identical markup. If this were a real app, ask a developer for a unique attribute per row — until then, position is genuinely your only lever.

    Zero-Attribute Element

    Hard
    Pending

    No id, class, or test id at all — just a bare <span>. In a real app, flag this to a developer; until then, text content is your only lever.

    Decoy-Attribute Trap

    Expert

    Every attribute on this button looks promising and is actually unreliable — a realistic example of why 'has an id' isn't the same as 'has a stable id'.

    SVG Icon Button

    Medium

    Sibling-Context-Only Element

    Expert
    Widget A
    Widget B

    Classic 'find the button in the row that contains X' problem — most frameworks solve this with a scoped/filtered locator (e.g. Playwright's .filter({ has: ... })), not a single global CSS selector.

    QA Bash's Element Playground is a free, live locator-practice page with 40+ interactive elements across 7 categories — text inputs, selection controls, buttons, dynamic/timing traps, overlays, iframes and shadow DOM, and deliberately ambiguous cases. Every element has a ranked locator list (best strategy to worst, with the real selector and why), and a live Selector Tester at the bottom evaluates any CSS selector or XPath you type against the real page, highlighting matches instantly.

    Features

    Practice pages, but with a feedback loop.

    Live Selector Tester

    Type any CSS selector or XPath and see it evaluated against the real page — matches get a pulsing highlight and a live count. Nowhere else lets you test the guess in place.

    Ranked locators per element

    Every element's info icon opens a ranked list — best strategy to worst — with the exact selector, a verdict, and why, not just a generic tip.

    40+ elements, 7 categories

    From a plain text input to a real shadow DOM component, a five-identical-buttons trap, and an ID that regenerates on every reload.

    Real overlays, not screenshots

    A focus-trapped modal, an auto-dismissing toast, a hover-only tooltip, a right-click context menu, and a state-dependent cookie banner — all genuinely interactive.

    Frames and shadow DOM done right

    Same-origin and nested iframes via srcDoc, plus a real attachShadow(mode:'open') component — watch the Selector Tester return 0 matches inside it and see why.

    Difficulty-tagged

    Easy through Expert, so you can specifically drill the hard cases — dynamic IDs, decoy attributes, sibling-scoped locators — instead of only the easy ones.

    FAQ

    Frequently asked questions.

    Is this free, and do I need an account?

    Yes to both — free, no signup required. Every element and the Selector Tester work without logging in.

    What's the difference between this and selectorshub.com's practice page?

    Every element here has a ranked, worked-example locator list (best strategy to worst, with the actual selector and why) built in, and the live Selector Tester lets you test your own guess against the real page and see it highlighted — most practice pages give you elements with no feedback loop at all.

    Why does the shadow DOM element show 0 matches when I test a selector on it?

    That's intentional and correct — standard CSS selectors and XPath genuinely cannot pierce an open shadow root from outside it. Playwright's locator() can; plain document.querySelectorAll() and XPath cannot. The 0-match result is the lesson.

    Do the ranked locators actually match the live markup?

    Yes — every selector shown in a Ranked Locators panel is copy-paste-able directly into the Selector Tester bar and will match the real element on the page.

    Can I use this to demo locator strategies to my team?

    Yes — it's a public page, so you can link directly to a category (e.g. #dynamic-timing) or a specific element card.

    Is there a backend API practice page too?

    Yes — see API Playground for a sample REST + GraphQL backend with CRUD, auth, and deliberate error cases (409 conflicts, 401 vs 403, flaky/slow/rate-limited endpoints).