tapWidget function
Future<TapResult>
tapWidget(
- TapInput input, {
- FdbHelperChecker? checkFdbHelperFn,
- FdbTapRunner? fdbTapFn,
Taps a widget or coordinates in the running Flutter app.
Handles selector-based taps, coordinate taps, and @N describe-ref taps.
A ref goes to fdb_helper as is: the helper resolves it to the widget it
names, or fails when that widget is gone, so a ref never lands on another
widget. The retry loop (500ms poll until deadline) runs inside this
function. Never throws; all error conditions are represented as sealed
result cases.
Implementation
Future<TapResult> tapWidget(
TapInput input, {
FdbHelperChecker? checkFdbHelperFn,
FdbTapRunner? fdbTapFn,
}) async {
try {
final isolateId = await (checkFdbHelperFn ?? checkFdbHelper)();
if (isolateId == null) return const TapNoFdbHelper();
final params = <String, dynamic>{'isolateId': isolateId};
if (input.text != null) params['text'] = input.text;
if (input.key != null) params['key'] = input.key;
if (input.type != null) params['type'] = input.type;
if (input.index != null) params['index'] = input.index.toString();
if (input.x != null) params['x'] = input.x.toString();
if (input.y != null) params['y'] = input.y.toString();
if (input.ref != null) params['ref'] = input.ref.toString();
if (input.expectText != null) params['expectText'] = input.expectText;
if (input.expectType != null) params['expectType'] = input.expectType;
final result = await _tapUntilDeadline(params, fdbTapFn ?? fdbTap, timeoutSeconds: input.timeoutSeconds);
return switch (result) {
TapSuccess(:final widgetType, :final x, :final y, :final warning, :final text) => TapSuccess(
widgetType: input.usedAt ? 'coordinates' : widgetType,
x: x ?? input.x ?? '',
y: y ?? input.y ?? '',
warning: warning,
text: describeEntryText(text),
),
TapRelayedError(:final message) => TapRelayedError(refAwareError(message, input.ref)),
_ => result,
};
} on AppDiedException catch (e) {
return TapAppDied(logLines: e.logLines, reason: e.reason);
} catch (e) {
return TapError(e.toString());
}
}