tap method

Future<void> tap(
  1. WidgetSelector<Widget> selector
)

Triggers a tap event on a given widget.

Implementation

Future<void> tap(WidgetSelector selector) async {
  // Check if widget is in the widget tree. Throws if not.
  final snapshot = selector.snapshot()..existsOnce();

  return TestAsyncUtils.guard<void>(() async {
    return _alwaysPropagateDevicePointerEvents(() async {
      // Find the associated RenderObject to get the position of the element on the screen
      final element = snapshot.discoveredElement!;
      final renderObject = element.renderObject;
      if (renderObject == null) {
        throw TestFailure(
          "Widget '${selector.toStringBreadcrumb()}' has no associated RenderObject.\n"
          "Spot does not know where the widget is located on the screen.",
        );
      }
      if (renderObject is! RenderBox) {
        throw TestFailure(
          "Widget '${selector.toStringBreadcrumb()}' is associated to $renderObject which "
          "is not a RenderObject in the 2D Cartesian coordinate system "
          "(implements RenderBox).\n"
          "Spot does not know how to hit test such a widget.",
        );
      }
      _validateViewBounds(renderObject, selector: selector);

      final centerPosition =
          renderObject.localToGlobal(renderObject.size.center(Offset.zero));

      // Before tapping the widget, we need to make sure that the widget is not
      // covered by another widget, or outside the viewport.
      _pokeRenderObject(
        position: centerPosition,
        target: renderObject,
        snapshot: snapshot,
      );

      final binding = TestWidgetsFlutterBinding.instance;

      // Finally, tap the widget by sending a down and up event.
      final downEvent = PointerDownEvent(position: centerPosition);
      binding.handlePointerEvent(downEvent);

      final upEvent = PointerUpEvent(position: centerPosition);
      binding.handlePointerEvent(upEvent);

      await binding.pump();
    });
  });
}