FISSION_TEST_CONTROL_PORT=9876 cargo run --example counter
Endpoint | Method | Meaning |
|---|---|---|
/health | GET | Readiness probe for the test-control server. |
/cmd | POST | Executes one JSON command and returns one JSON response. |
{"cmd":"GetTree"}
{
"selector": {
"kind": "semantic_identifier",
"identifier": "settings.save"
}
}
Field | Type | Default | Meaning |
|---|---|---|---|
selector | selector object | required | Primary selector. |
scope | nested selector query | omitted | Restrict matches to descendants of the scoped node. |
index | number | omitted | Select the Nth candidate after filtering. Useful for intentional duplicate labels. |
include_hidden | boolean | false | Include hidden nodes during resolution. Most user-level tests should leave this false. |
Kind | Fields | Matches |
|---|---|---|
semantic_identifier | identifier | Semantics::identifier, exposed as SemanticNode.identifier. |
widget_id | widget_id | Stable widget id. Accepts an explicit widget id key or raw id string. |
test_id | test_id | Test identifier. Currently aliases semantic identifier. |
accessibility_identifier | identifier | Accessibility identifier. Currently aliases semantic identifier. |
role_label | role, label | Node with both matching role and label. |
label | label | Node with matching label. |
{
"selector": { "kind": "label", "label": "Continue" },
"scope": {
"selector": {
"kind": "semantic_identifier",
"identifier": "checkout.payment_dialog"
}
}
}
Status | Fields | Meaning |
|---|---|---|
Ok | none | Command completed. |
Text | items | Visible text records returned by GetText. |
Tree | nodes | Semantic tree returned by GetTree. |
Screenshot | png_base64, width, height | PNG screenshot payload. |
SelectorResolved | node | Selector resolved to one node. |
SelectorError | failure | Selector failed with structured diagnostic data. |
Error | message | Non-selector command failure. |
Field | Meaning |
|---|---|
identifier | First-class semantic identifier. Do not overload value for this. |
widget_id | Widget id string. |
stable_node_id | Stable test node id for parent/child relationships. |
parent | Parent stable_node_id, if any. |
children | Child stable_node_id values. |
role | Semantic/accessibility role, such as Button, TextInput, Checkbox, or Radio. |
label | User-facing or accessibility label. |
value | Current value if the node exposes one. |
value_present | Whether a value exists, including masked or empty values. |
focusable | Whether the node can receive focus. |
disabled | Whether activation should be blocked. |
read_only | Whether text/value editing should be blocked. |
checked | Toggle state for checkbox, switch, radio, or similar controls. |
actions | Supported semantic actions. |
text_selection | Text selection byte offsets when exposed. |
masked | Whether the value is masked, for example password input. |
scrollable_x, scrollable_y | Whether the node scrolls in that axis. |
logical_bounds | Full logical bounds before clipping. |
visible_bounds | Bounds after viewport/clipping, or null when hidden. |
visibility | FullyVisible, PartiallyVisible, or Hidden. |
x, y, width, height | Compatibility bounds matching logical_bounds. |
{"cmd":"Tap","x":120,"y":48}
{"cmd":"Drag","start_x":40,"start_y":40,"end_x":240,"end_y":120,"steps":12}
{"cmd":"TapText","text":"Add task"}
{"cmd":"ResolveSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"todo.add"}}}
{"cmd":"TapSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"todo.add"}}}
{"cmd":"ActivateSelector","query":{"selector":{"kind":"role_label","role":"Button","label":"Save"}}}
{"cmd":"FocusSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"login.email"}}}
{"cmd":"HoverSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"toolbar.help"}}}
{"cmd":"RightClickSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"editor.selection"}}}
{"cmd":"ScrollIntoView","query":{"selector":{"kind":"semantic_identifier","identifier":"page.3"}}}
{"cmd":"FillText","query":{"selector":{"kind":"semantic_identifier","identifier":"login.password"}},"text":"secret"}
{"cmd":"ClearText","query":{"selector":{"kind":"semantic_identifier","identifier":"search.query"}}}
{"cmd":"Toggle","query":{"selector":{"kind":"semantic_identifier","identifier":"settings.sync"}}}
{"cmd":"SelectOption","query":{"selector":{"kind":"semantic_identifier","identifier":"plan.pro"}}}
{"cmd":"WaitForSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"toast.saved"}},"timeout_ms":5000}
{"cmd":"WaitForVisible","query":{"selector":{"kind":"semantic_identifier","identifier":"toast.saved"}},"timeout_ms":5000}
{"cmd":"WaitForEnabled","query":{"selector":{"kind":"semantic_identifier","identifier":"submit"}},"timeout_ms":5000}
{"cmd":"WaitForDisabled","query":{"selector":{"kind":"semantic_identifier","identifier":"submit"}},"timeout_ms":5000}
{"cmd":"WaitForValue","query":{"selector":{"kind":"semantic_identifier","identifier":"search.query"}},"value":"release","timeout_ms":5000}
{"cmd":"WaitForText","text":"Saved","timeout_ms":5000}
{"cmd":"WaitForGone","query":{"selector":{"kind":"semantic_identifier","identifier":"loading.spinner"}},"timeout_ms":5000}
{"cmd":"Scroll","x":400,"y":300,"dx":0,"dy":480}
{"cmd":"ExternalFileHover","x":320,"y":240,"paths":["/tmp/example.txt"]}
{"cmd":"ExternalFileDrop","x":320,"y":240,"paths":["/tmp/example.txt"]}
{"cmd":"ExternalFileCancel"}
{"cmd":"TypeText","text":"hello"}
{"cmd":"ImePreedit","text":"かな","cursor_start":0,"cursor_end":2}
{"cmd":"ImeCommit","text":"かな"}
{"cmd":"ImeCancel"}
{"cmd":"PressKey","key":"Enter","modifiers":0}
{"cmd":"Screenshot","path":"/tmp/app.png"}
{"cmd":"CaptureScreenshot"}
{"cmd":"GetText"}
{"cmd":"GetTree"}
{"cmd":"Wait","ms":250}
{"cmd":"Pump"}
{"cmd":"Quit"}
{"cmd":"SimulateMouseMove","x":100,"y":100}
{"cmd":"SimulateRightClick","x":100,"y":100}
{"cmd":"SimulateResize","width":390,"height":844}