invokeSemanticAction method
Future<SemanticActionInvocationResult>
invokeSemanticAction(
- SemanticAction action, {
- SemanticNode? node,
- SemanticNodeId? id,
- SemanticRole? role,
- String? label,
- Object? value,
- Object? payload,
- bool? focused,
- bool? selected,
- bool? enabled,
- bool? checked,
- bool? busy,
- String? validationError,
Invokes a semantic action on a node in the current semantic tree.
When node is omitted, the remaining filters must identify exactly one
node before checking action availability. Tests
can exercise app commands, controls, fields, and app-authored regions by
role/label/action instead of reaching through widget internals.
Requested frames continue while the handler is pending, without advancing test time. Dialog-opening handlers still need an explicit answer.
For SemanticAction.setValue, pass the value to apply as payload (the
value argument is a node filter, not the payload).
Implementation
Future<SemanticActionInvocationResult> invokeSemanticAction(
SemanticAction action, {
SemanticNode? node,
SemanticNodeId? id,
SemanticRole? role,
String? label,
Object? value,
Object? payload,
bool? focused,
bool? selected,
bool? enabled,
bool? checked,
bool? busy,
String? validationError,
}) async {
_assertNotDisposed('invokeSemanticAction');
final root = _root;
if (root == null) {
return SemanticActionInvocationResult.notFound(action);
}
final tree = semantics();
final SemanticNode target;
try {
target = _resolveSemanticActionTarget(
tree,
node: node,
id: id,
role: role,
label: label,
value: value,
focused: focused,
selected: selected,
enabled: enabled,
checked: checked,
busy: busy,
validationError: validationError,
);
} on SemanticQueryError catch (error) {
return error.matchCount == 0
? SemanticActionInvocationResult.notFound(action, error: error)
: SemanticActionInvocationResult.ambiguous(action, error: error);
}
if (!target.enabled) {
return SemanticActionInvocationResult.disabled(target, action);
}
if (!target.actions.contains(action)) {
return SemanticActionInvocationResult.unsupported(target, action);
}
// Dispatch through the same map-based path the live wire uses, so the tester
// can't pass where production fails (the divergence that previously hid a
// cross-fire bug). The tree from `semantics()` carries the id→element map.
final result = await _runAction(
() => invokeSemanticActionFromElement(
tree: tree,
id: target.id,
action: action,
value: payload,
),
);
_owner.flushBuild();
return result;
}