Skip to main content

Locators

letsrunit resolves locators in priority order: accessible names first, then visible text, then raw selectors. Prefer descriptive locators over attribute-based ones. They survive UI changes better.

Locator patterns

PatternExampleMatches
button "text"button "Sign in"<button> by visible text or aria-label
link "text"link "Home"<a> by link text
field "label"field "Email"<input> by label text, placeholder, or aria-label
text "content"text "Welcome"Any element containing the text (substring match)
image "alt"image "Logo"<img> by alt attribute
date "value"date "2025-01-22"Element by a specific date
date of {expr}date of tomorrowRelative date expression
{role} "name"menuitem "Profile"Element by ARIA role and accessible name
{tag}sectionHTML tag name
`selector``.btn-primary`Raw Playwright/CSS selector

Scoping and filtering

Scope a locator to a parent element with within:

When I click button "Submit" within `#checkout-form`

Filter by descendants with with or without:

Then the page contains section with button "Save"
Then the page contains section without text "Expired"

Relative dates

When I set field "Appointment" to date of tomorrow
When I set field "Appointment" to date of 3 days ago
When I set field "Appointment" to date of 8 weeks from now
When I set field "Appointment" to date of 1 week from now at 20:00

When to use raw selectors

Use a raw `selector` when no natural-language locator reliably identifies the element, for example elements with no accessible name or visible text:

# Toggle-all checkbox has no visible label
When I click `#toggle-all`
warning

Raw selectors are fragile. Prefer field, button, link, or text locators wherever possible. Fall back to a raw selector only when the element has no accessible name or meaningful visible text.

Common pitfalls

Ambiguous locator: if multiple elements match, the step fails. Narrow the match with within or use a more specific pattern.

Element not visible: letsrunit waits for elements to be visible before interacting. If the step times out, check whether the element is hidden behind a modal or requires scrolling.

Dynamic text: for text that changes (user names, IDs, timestamps), use a partial match with text "..." rather than button or link which match more exactly.