Working with Wrk’s Selection Methods in Web Automation
Selecting the right element is a foundational part of reliable web automation. Wrk provides two generations of selection capabilities, a legacy CSS-based approach and a modern locator-based model built around a flexible Element identifier.
As web applications become more dynamic and interactive, element selection needs to be expressive, resilient, and easy to reason about. Wrk’s Element identifier is designed to meet those needs while remaining approachable for anyone familiar with the basics of web automation.
Advanced
The Advanced Selection Method in Wrk's Web automation introduces locators(based on Playwright's Locators), a richer interpretation of the Element identifier.
Instead of being limited to CSS, an Element identifier can now be a composed selector string that combines different selector types into a single expression.
This makes it possible to describe elements based on what they are, what they contain, and where they appear, rather than relying only on DOM structure.
Supported Selector Types
Wrk Element identifiers support multiple selector engines, each suited to different situations.
CSS selectors
CSS selectors remain fully supported and are commonly used for structural scoping.
div.modal# Find a div that has the class modal
button.primary# Find a button that has the class primary
They are especially useful for narrowing the search to a specific section of the page.
XPath selectors
XPath is supported for more complex relationships that are difficult to express in CSS.
//section[@id="pricing"]# Find the section of the page that is the pricing section.
xpath=.//button[contains(., "Buy")]# Find any button that has the word ‘Buy’ in it.
Relative XPath expressions work well when combined with other selectors.
Semantic and Engine-Based Selectors
Wrk supports multiple selector engines, each designed for a specific way of identifying elements. These engines can be used on their own or combined together in a single Element identifier.
Selector engine overview
| Selector engine | What it selects by | Example | When to use it |
|---|---|---|---|
css | Page structure and attributes | css=div.modal | Scoping to sections or containers |
xpath | Structural relationships | xpath=//section[@id="pricing"] | Complex relationships not expressible in CSS |
role | Accessibility role and name | role=button[name="Submit"] | Interactive elements like buttons and dialogs |
text | Visible text content | text=Welcome | Selecting elements by what the user sees |
id | ID attribute | id=submit_btn | Selecting elements by its id attribute |
data-testid | Stable automation attributes | [data-testid=login-btn] | Elements with dedicated automation IDs |
placeholder | Input placeholder text | [placeholder="Email address"] | Inputs with meaningful placeholders |
alt | Alternative text | [alt="Company logo"] | Images and icons |
title | Title attribute | [title=Close] | Tooltips or icon-only controls |
href | href attribute | [href=/login] | Buttons or links with a known URL |
How these engines work together
Each selector engine focuses on a different aspect of the page. When combined using >>, they form a clear, step-by-step description of how to find an element.
Example:
css=div.modal >> role=button[name="Close"]
This can be read as:
Find the modal container, then within it find the Close button.
It represents a left-to-right resolution process:
- Find elements matching the first selector
- Search within those elements using the next selector
- Continue until the final selector is resolved
Each part of the identifier further narrows the scope, making complex selections easier to understand. Note this can be done by mixing multiple selector engines together like in the example above. This allows each step to use the selector type that best fits the situation.
You also refine a selector for a given element by using attributes or filters on a single selector:
role=button[name="Submit"]
css=button:has-text("Submit")
You can expand the sections below to see more details and examples of filters for each Selector engine:
css
Supported filters
- Tag name
- Classes and IDs
- Attribute selectors
- Pseudo-classes
- Structural selectors
Examples
css=button.primarycss=input[type="email"]css=button:has-text("Submit")
xpath
Supported filters
- Attributes
- Text (exact or partial)
- Hierarchy
- Position
- Logical conditions
Examples
xpath=//button[contains(text(),"Submit")]xpath=//input[@type="email" and @required]
role
Available Roles
"alert" | "alertdialog" | "application" | "article" | "banner" | "blockquote" | "button" | "caption" | "cell" | "checkbox" | "code" | "columnheader" | "combobox" | "complementary" | "contentinfo" | "definition" | "deletion" | "dialog" | "directory" | "document" | "emphasis" | "feed" | "figure" | "form" | "generic" | "grid" | "gridcell" | "group" | "heading" | "img" | "insertion" | "link" | "list" | "listbox" | "listitem" | "log" | "main" | "marquee" | "math" | "meter" | "menu" | "menubar" | "menuitem" | "menuitemcheckbox" | "menuitemradio" | "navigation" | "none" | "note" | "option" | "paragraph" | "presentation" | "progressbar" | "radio" | "radiogroup" | "region" | "row" | "rowgroup" | "rowheader" | "scrollbar" | "search" | "searchbox" | "separator" | "slider" | "spinbutton" | "status" | "strong" | "subscript" | "superscript" | "switch" | "tab" | "table" | "tablist" | "tabpanel" | "term" | "textbox" | "time" | "timer" | "toolbar" | "tooltip" | "tree" | "treegrid" | "treeitem"
Supported filters
namecheckeddisabledexpandedpressedselectedlevel(headings)
Examples
role=button[name="Submit"]role=checkbox[checked=true]
Regex support(Name only)
role=button[name=/submit|save/i]role=heading[name=/pricing/i]
text
Supported filters
- Exact or partial text
Examples
text=Welcome text="Sign in"
Regex support
text=/welcome/i text=/sign\s*in/i
id
Supported filters
- ID attribute (exact or partial)
Examples
id=submit_btn
Regex support
label=/submit/i
data-testid
Supported filters
- Explicit automation ID
Examples
[data-testid="login-btn"] exact match[data-testid^="login"] starts with[data-testid$="btn"] ends with[data-testid*="log"] contains
placeholder
Supported filters
- Placeholder text
Examples
[placeholder="Email address"] exact match[placeholder^="Email"] starts with[placeholder$="address"] ends with[placeholder*="Email"] contains
alt
Supported filters
- Alt text
Examples
[alt="Company logo"] exact match[alt^="Company"] starts with[alt$="logo"] ends with[alt*="Company"] contains
title
Supported filters
- Title value
Examples
[title="Close button"] exact match[title^="Close"] starts with[title$="button"] ends with[title*="Close"] contains
href
Supported filters
- href value
Examples
[href="/account/login"] exact match[href^="/account"] starts with[href$="?ref=dashboard"] ends with[href*="/orders/"] contains
Why this matters
Using the right selector engine makes Element identifiers:
- Easier to read and understand
- More resilient to layout and styling changes
- Better aligned with how users interact with the page
Automation becomes clearer when selectors describe what an element is, not just where it happens to be.
Why This Approach Works Well for Automation
Compared to CSS-only selection, locator-based Element identifiers provide:
- Clear expression of intent
- Better resilience to UI changes
- Easier composition and reuse
- A single string representation that is easy to inspect and troubleshoot
This makes automations easier to maintain as applications evolve.
Legacy
Wrk’s original selection system supports standard CSS selectors only.
In this mode, the Element identifier is interpreted strictly as a CSS selector.
Examples of legacy Element identifiers:
.login-form button.submit
#email
ul.menu > li.active a
Strengths of the legacy approach
- Familiar and widely understood syntax
- Simple and predictable behavior
- Works well for basic structural selection
Limitations
While CSS selectors are powerful, they can be limiting in automation scenarios:
- They describe page structure rather than meaning
- Small layout or markup changes can break automations
- Selecting by visible text or purpose is difficult
- Long selectors can become hard to read and maintain
These challenges become more noticeable as automations grow in size or need to survive UI changes.
Choosing the Right Selection Method
The Advanced Selection Method, locator-based Element identifier, is the recommended starting point for Web Automation. It provides greater flexibility, clearer intent, and better long-term maintainability, even for simple scenarios. The Legacy Selector is available to ensure backwards compatibility but should not be used in new automation builds.