LiveTest command API
Fission live tests drive a running app through an HTTP test-control server. The server is enabled by launching a supported shell with FISSION_TEST_CONTROL_PORT=<port>.
FISSION_TEST_CONTROL_PORT=9876 cargo run --example counter
The protocol has two endpoints:
| | |
|---|
| | Readiness probe for the test-control server. |
| | Executes one JSON command and returns one JSON response. |
Every /cmd payload is tagged by the exact cmd variant name:
{"cmd":"GetTree"}
LiveTestClient in fission-test-driver wraps this protocol for Rust tests. Direct /cmd calls are still useful for manual QA, screenshot capture, CI diagnostics, and non-Rust clients.
Selector queries
Selector-driven commands receive a query object:
{
"selector": {
"kind": "semantic_identifier",
"identifier": "settings.save"
}
}
SelectorQuery fields:
| | | |
|---|
| | | |
| | | Restrict matches to descendants of the scoped node. |
| | | Select the Nth candidate after filtering. Useful for intentional duplicate labels. |
| | | Include hidden nodes during resolution. Most user-level tests should leave this false. |
Selector kinds:
| | |
|---|
| | Semantics::identifier, exposed as SemanticNode.identifier. |
| | Stable widget id. Accepts an explicit widget id key or raw id string. |
| | Test identifier. Currently aliases semantic identifier. |
| | Accessibility identifier. Currently aliases semantic identifier. |
| | Node with both matching role and label. |
| | Node with matching label. |
Scoped query example:
{
"selector": { "kind": "label", "label": "Continue" },
"scope": {
"selector": {
"kind": "semantic_identifier",
"identifier": "checkout.payment_dialog"
}
}
}
Responses
All responses are tagged by status.
| | |
|---|
| | |
| | Visible text records returned by GetText. |
| | Semantic tree returned by GetTree. |
| png_base64, width, height | |
| | Selector resolved to one node. |
| | Selector failed with structured diagnostic data. |
| | Non-selector command failure. |
SelectorError.failure.kind is one of NoMatch, Ambiguous, FoundButNotVisible, Disabled, ReadOnly, UnsupportedAction, Timeout, or StaleFrame. The failure also includes the selector, considered candidates, rejection reasons, and a message.
Semantic nodes returned by GetTree
GetTree returns SemanticNode records. Bounds are logical test-space pixels.
| |
|---|
| First-class semantic identifier. Do not overload value for this. |
| |
| Stable test node id for parent/child relationships. |
| Parent stable_node_id, if any. |
| Child stable_node_id values. |
| Semantic/accessibility role, such as Button, TextInput, Checkbox, or Radio. |
| User-facing or accessibility label. |
| Current value if the node exposes one. |
| Whether a value exists, including masked or empty values. |
| Whether the node can receive focus. |
| Whether activation should be blocked. |
| Whether text/value editing should be blocked. |
| Toggle state for checkbox, switch, radio, or similar controls. |
| Supported semantic actions. |
| Text selection byte offsets when exposed. |
| Whether the value is masked, for example password input. |
scrollable_x, scrollable_y | Whether the node scrolls in that axis. |
| Full logical bounds before clipping. |
| Bounds after viewport/clipping, or null when hidden. |
| FullyVisible, PartiallyVisible, or Hidden. |
| Compatibility bounds matching logical_bounds. |
Command reference
Tap
{"cmd":"Tap","x":120,"y":48}
Taps logical coordinates with the primary pointer button. Use selector commands for product tests; use Tap for low-level hit-testing bugs.
Drag
{"cmd":"Drag","start_x":40,"start_y":40,"end_x":240,"end_y":120,"steps":12}
Sends mouse move, primary down, intermediate moves, and primary up.
TapText
{"cmd":"TapText","text":"Add task"}
Finds visible text containing text and taps its center. Kept for simple tests and backward compatibility. Prefer selectors when possible.
ResolveSelector
{"cmd":"ResolveSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"todo.add"}}}
Resolves a selector and returns SelectorResolved with the matching semantic node, or SelectorError.
TapSelector
{"cmd":"TapSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"todo.add"}}}
Auto-scrolls the target into view, then sends a primary pointer click at the visible target. Fails clearly if the node is missing, ambiguous, disabled, or still not visible.
ActivateSelector
{"cmd":"ActivateSelector","query":{"selector":{"kind":"role_label","role":"Button","label":"Save"}}}
Invokes the node's semantic activation path. Use when you want to express "activate this control" rather than pointer-click mechanics.
FocusSelector
{"cmd":"FocusSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"login.email"}}}
Auto-scrolls and focuses a focusable node.
HoverSelector
{"cmd":"HoverSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"toolbar.help"}}}
Moves the pointer to the selector target without clicking. Useful for tooltip, hover, and drag-hover states.
RightClickSelector
{"cmd":"RightClickSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"editor.selection"}}}
Auto-scrolls and right-clicks the selector target. Use for context menus and secondary-click behaviour.
{"cmd":"ScrollIntoView","query":{"selector":{"kind":"semantic_identifier","identifier":"page.3"}}}
Scrolls the nearest scroll container so the target is visible, then returns the resolved node. This reuses the runtime scroll-into-view behaviour rather than duplicating scrolling in tests.
FillText
{"cmd":"FillText","query":{"selector":{"kind":"semantic_identifier","identifier":"login.password"}},"text":"secret"}
Auto-scrolls, focuses, replaces the editable value, and pumps the result. For masked fields, assert value_present or masked through GetTree instead of printing the secret.
ClearText
{"cmd":"ClearText","query":{"selector":{"kind":"semantic_identifier","identifier":"search.query"}}}
Auto-scrolls, focuses, and clears an editable value.
Toggle
{"cmd":"Toggle","query":{"selector":{"kind":"semantic_identifier","identifier":"settings.sync"}}}
Toggles a checkbox, switch, radio-like control where supported, or another control exposing a toggle action. Disabled nodes fail with SelectorError.
SelectOption
{"cmd":"SelectOption","query":{"selector":{"kind":"semantic_identifier","identifier":"plan.pro"}}}
Activates a selectable option. This is useful for options rendered in menus, popovers, portals, or dropdown lists.
WaitForSelector
{"cmd":"WaitForSelector","query":{"selector":{"kind":"semantic_identifier","identifier":"toast.saved"}},"timeout_ms":5000}
Polls until a selector resolves.
WaitForVisible
{"cmd":"WaitForVisible","query":{"selector":{"kind":"semantic_identifier","identifier":"toast.saved"}},"timeout_ms":5000}
Polls until a selector resolves to a visible node.
WaitForEnabled
{"cmd":"WaitForEnabled","query":{"selector":{"kind":"semantic_identifier","identifier":"submit"}},"timeout_ms":5000}
Polls until a selector resolves to a node that is not disabled.
WaitForDisabled
{"cmd":"WaitForDisabled","query":{"selector":{"kind":"semantic_identifier","identifier":"submit"}},"timeout_ms":5000}
Polls until a selector resolves to a disabled node.
WaitForValue
{"cmd":"WaitForValue","query":{"selector":{"kind":"semantic_identifier","identifier":"search.query"}},"value":"release","timeout_ms":5000}
Polls until the selector's semantic value matches value.
WaitForText
{"cmd":"WaitForText","text":"Saved","timeout_ms":5000}
Polls visible text until any item contains text.
WaitForGone
{"cmd":"WaitForGone","query":{"selector":{"kind":"semantic_identifier","identifier":"loading.spinner"}},"timeout_ms":5000}
Polls until a selector no longer resolves.
{"cmd":"Scroll","x":400,"y":300,"dx":0,"dy":480}
Sends a wheel/scroll event at logical coordinates.
ExternalFileHover
{"cmd":"ExternalFileHover","x":320,"y":240,"paths":["/tmp/example.txt"]}
Simulates dragging external files over the app at coordinates.
ExternalFileDrop
{"cmd":"ExternalFileDrop","x":320,"y":240,"paths":["/tmp/example.txt"]}
Simulates dropping external files on the app at coordinates.
ExternalFileCancel
{"cmd":"ExternalFileCancel"}
Cancels an external file drag session.
TypeText
{"cmd":"TypeText","text":"hello"}
Sends text input to the currently focused control. Prefer FillText for form automation.
ImePreedit
{"cmd":"ImePreedit","text":"かな","cursor_start":0,"cursor_end":2}
Sends an IME preedit update to the focused control.
ImeCommit
{"cmd":"ImeCommit","text":"かな"}
Commits IME text to the focused control.
ImeCancel
{"cmd":"ImeCancel"}
Cancels the active IME preedit session.
PressKey
{"cmd":"PressKey","key":"Enter","modifiers":0}
Sends key down and key up for the named key. modifiers is the shell modifier bitmask used by the test driver.
Screenshot
{"cmd":"Screenshot","path":"/tmp/app.png"}
Requests a screenshot written by the app process to path and returns Ok or Error. Prefer CaptureScreenshot when the caller should own the file write.
CaptureScreenshot
{"cmd":"CaptureScreenshot"}
Returns Screenshot with png_base64, width, and height.
GetText
{"cmd":"GetText"}
Returns visible text items with text and logical bounds.
GetTree
{"cmd":"GetTree"}
Returns the current semantic tree, including first-class identifier, role, label, value state, focusability, disabled/read-only state, checked state, actions, text selection, masking, scrollability, parent/child relationships, logical bounds, visible bounds, and visibility.
Wait
{"cmd":"Wait","ms":250}
Sleeps on the test-control side and returns Ok. Prefer condition-based waits when possible.
Pump
{"cmd":"Pump"}
Requests a frame pump and returns after the shell has processed it.
Quit
{"cmd":"Quit"}
Requests application shutdown.
SimulateMouseMove
{"cmd":"SimulateMouseMove","x":100,"y":100}
Sends a low-level mouse move through the shell event path.
SimulateRightClick
{"cmd":"SimulateRightClick","x":100,"y":100}
Sends low-level mouse move, secondary down, and secondary up events.
SimulateResize
{"cmd":"SimulateResize","width":390,"height":844}
On native hosts, resizes the logical test viewport. On the Rust Chromium
transport, client.simulate_resize(390, 844) resizes the same browser page in
CSS pixels and waits for actual metrics, canvas/layout frame acknowledgement
(Web), and paint. State and route survive. The configured device scale and mobile
mode are preserved (scale 1 and desktop mode by default);
dimensions are 1–8192 per axis, at most 16,777,216 pixels total. Same-size
requests verify the existing matching frame. The deadline is the browser
options timeout capped at 60 seconds.
Use LiveTestClient::launch_browser(BrowserTestOptions::new(url).fission_canvas())
against a Web build compiled with FISSION_WEB_TEST_CONTROL=1 (for example,
FISSION_WEB_TEST_CONTROL=1 ./platforms/web/build-wasm.sh) and served through
the existing Web server or your test host. Raw Web bridge dispatch has
no Chromium control: it returns Error with unsupported_host and that exact
driver path without changing runtime dimensions. Static DOM uses
BrowserTestOptions::new(url) and requires no bridge. Other DOM semantic
commands remain unsupported. Capture with client.capture_screenshot_png();
PNG dimensions use the configured device scale, so a 360×844 CSS viewport at
scale 3 produces 1080×2532 pixels. Content still needs visual review.
Failure includes last observed state; host metrics may already have changed.
Repair the cause and retry the supported resize. Capture rejects mismatching
or stale frames. Drop and relaunch the owned client for a closed page/lost host.
See Web test control
for examples, waiting and recovery details. Best-practice command order
For stable end-to-end tests:
GET /health or LiveTestClient::wait_for_ready.
WaitForVisible on a stable semantic identifier.
Selector action such as FillText, TapSelector, or ActivateSelector.
WaitForValue, WaitForText, WaitForGone, or GetTree assertion.
CaptureScreenshot only when visual evidence is required.
Avoid fixed Wait sleeps unless you are debugging timing itself.