flutter / flutter/flutter

[flutter_test] Add an option to hide pointer crosshairs in live tests

Open
#189,982 2 comments 0 reactions 1 assignee Claimed by @Laurie-Lin View on GitHub
a: tests c: proposal framework P3 team-framework triaged-framework
Dominant language
Dart
Stars
179k
Forks
31.1k
PR merge metrics
PR metrics pending

Description

## Use case

`LiveTestWidgetsFlutterBinding` paints a circular crosshair for pointer events
generated by `WidgetTester`, `TestGesture`, and other test APIs. The overlay is
helpful when watching an interactive test, but there is currently no public API
to disable it.

Some live-test use cases need test-generated input without additional visuals:

- Capturing clean screenshots or golden images.
- Recording demos driven by `WidgetTester`.
- Running debug/runtime automation while observing the real application UI.
- Providing a custom pointer visualization in a test harness.

For example, the following live test displays a crosshair at the button:

```dart
void main() {
final binding = LiveTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;

testWidgets('tap a button', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Center(
child: FilledButton(
onPressed: () {},
child: const Text('Tap'),
),
),
),
);

await tester.tap(find.text('Tap'));
await tester.pump();
});
}
```

Changing `LiveTestWidgetsFlutterBinding.framePolicy` is not an equivalent
workaround. A frame policy controls when frames are scheduled and rendered,
whereas this request only concerns whether the test pointer overlay is shown.
For example, switching away from `fullyLive` can change animation and pumping
behavior that the test relies on.

Waiting for the crosshair to fade adds unnecessary delays and can make
screenshot timing fragile. A package cannot cleanly solve this either because
the pointer records and painting logic are private implementation details of
`LiveTestWidgetsFlutterBinding`.

Flutter issue
[#128100](https://github.com/flutter/flutter/issues/128100) previously
described pointer crosshairs appearing in integration-test screenshots. An
explicit visibility option would also address that use case.

## Proposal

Add a public, backward-compatible option to
`LiveTestWidgetsFlutterBinding`:

```dart
final binding = LiveTestWidgetsFlutterBinding.ensureInitialized();
binding.showTestPointerCrosshairs = false;
```

Proposed API:

```dart
/// Whether pointer crosshairs generated by test pointer events are shown.
///
/// This only affects the visual representation of test pointers. Pointer
/// events are still dispatched normally when this property is false.
///
/// This property is independent of [framePolicy], which controls how frames
/// are scheduled.
///
/// Defaults to true.
bool get showTestPointerCrosshairs;
set showTestPointerCrosshairs(bool value);
```

The property would default to `true`, preserving existing behavior.

When set to `false`, the binding would:

- Stop creating and updating `_LiveTestPointerRecord` objects.
- Clear any active pointer records and schedule a repaint so an existing
crosshair disappears immediately.
- Continue forwarding test pointer events to
`super.handlePointerEvent(event)`.
- Leave device-sourced pointer handling and frame-policy behavior unchanged.

This keeps pointer visualization configurable without coupling it to event
delivery or frame scheduling.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.