StrikekitStrikekit

UI contracts

DOM and ARIA shapes each command and qualifier actually resolve — diagnose timeouts as wrong control shape, not wrong label

StrikeTest finds controls by labels and fixed DOM/ARIA shapes, never by CSS or XPath in .stk. A timeout or element not found often means the control shape does not match the command — not that the quoted label string is typo’d.

Every command page has a Requirements section. This hub is the master map.

Scope layers

LayerCommandWhat it scopes
iframe / framescope toResolution root for later steps
Element stackin (command)Nested region under current root
One-shot containerclick on "…" in "…" / should in "…" seeAction or assert inside a container; does not push the in stack
One-shot row… in row "…"Action or assert inside a table row

Find hints (by …) apply to the primary target only. Container and row keys always use auto-find.

Find hints vs auto-find

Without by …, each command uses its own auto-find candidate list. With by …, that single strategy replaces the auto chain.

HintResolves by
by idElement #id
by data-testid[data-testid='…']
by aria-label[aria-label='…']
by name[name='…'] (any tag)
by textClickables only: button, a, input[type=button], [role=button], [role=link], [role=tab]
by role "R"[role='R'] + accessible name (aria-label, else direct text nodes)
by attributeUnique visible presence of the attribute named by the label

Auto data-* fallback (web, no by …): if auto-find misses and the label is a valid data-* attribute name, a unique visible element that has that attribute may still resolve. Ambiguous (2+) fails.

Details: Find hints.

Auto-find cheat sheet

General resolve (ResolveByLabel — hover, many clicks, toggle, most should have): fill candidates → click candidates → checkbox candidates.

PoolOrder (exact label)
fillid → input/textarea data-testid → input/textarea aria-label → input name → input placeholder → textarea name → textarea placeholder
clickid → data-testid → aria-label → role=tab + exact text → visible text on button / a / input[type=button] only → submit value
checkboxcheckbox id → data-testid → aria-label → name

Critical nuance: default page click on "Login" visible text does not match [role=button]. Use by text, by role "button", id/testid/aria-label, or click … in / in row (those do include [role=button]).

Specialized pathOrder / shape
Containerrole=dialog HasText → data-testid → aria-label → heading text → general resolve
Rowtr or role=row containing key text
Click in container (action)button → a → role=button → id → data-testid → aria-label
Click in row (action)button → a → role=button (no id/testid/aria in auto path)
Columnrole=columnheader + text → th + text → th[aria-label]
Native selectselect id → data-testid → aria-label → name → label + select
Combobox triggercombobox#id → data-testid → combobox aria-label → button[aria-haspopup] → button text → label + combobox → input[role=combobox]
Combobox panelvisible role=listbox or role=menu (prefer aria-controls / aria-owns)
File inputfile id → data-testid → aria-label → name → label ≫ file (hidden OK)
Date / timearia-label → label + input → id
Range (set)aria-label → label + range → id → name
iframe (scope)iframe/frame title, name, aria-label

Command → UI shape

Command familyRequired UI shape
click on (default)id / data-testid / aria-label; or tab text; or text on button/a/input[type=button]; submit value
click + by textAlso [role=button], [role=link], [role=tab]
click … in / in rowContainer/row contracts + action includes [role=button]
click … columnColumn header / th
fill / clear / press … oninput / textarea only
selectNative <select>
open / pickCombobox trigger + listbox/menu panel + option/li inside panel
type … and pickResolvable field + same panel/option as combobox
uploadinput[type=file]
setinput[type=range]
pick date / pick timeNative date / time inputs
toggleCheckable / switch-like
hover / double·right·force click / scroll to / dragGeneral resolve
scope toiframe / frame
in (command)Container resolve per stack frame
should seeAny visible text (iframe scope; element stack ignored on bare see)
should on/in / in row seeContainer / row contracts
should haveGeneral resolve (+ count / sum / sorted rules)
accept / dismissNo DOM — dialog message fragment
accept cookiesAllowlist button labels via general resolve
Page / API opsNo element contract

Wrong shape → use instead

UI patternWrong commandUse instead
Native <select>open / pickselect "…" from "…"
ARIA combobox / aria-haspopup buttonBare option text clickopen / pick
Radix / menu role=menuitemopen … and pick, bare text click on itemclick trigger by id + click item by id
<div role="button"> with no <button>Default click on "text"by text, by role "button", or id / aria-label / data-testid
Plain <div> with only textclick / openReal button/link, or add id / aria-label / role=button + correct hint
Custom date / time widgetpick date / pick timeNative inputs, or fill/test hooks
Custom slidersetNative range, or other supported control
Contenteditable / custom editorfillNative input / textarea
# Radix / Headless menu (not combobox)
When I click on "filter-trigger" by id
And I click on "filter-item-1" by id

Failure glossary

Error patternTypical cause
element not found (tried …)No candidate matched — wrong label or wrong control shape / scope
ambiguous … (matched N …)Duplicate id/testid/text; glob matched multiple
timed out after …Action auto-wait exhausted (DOM not ready or shape never appears)
element is disabledResolved a disabled control
toggle …: not checkableTarget is not checkbox/switch/radio-like
set …: not a native range inputUsed set on a non-range control
Combobox panel did not open / multiple open panelsTrigger is not combobox-shaped, or panels lack ownership
frame "…" not foundBad iframe label or frame not visible
be visible fails as not foundNode was removed from the DOM — that is not a successful not be visible

On this page