// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'semantics_tester.dart';

Future<void> pumpTest(
  WidgetTester tester,
  TargetPlatform? platform, {
  bool scrollable = true,
  bool reverse = false,
  Set<LogicalKeyboardKey>? axisModifier,
  Axis scrollDirection = Axis.vertical,
  ScrollController? controller,
  bool enableMouseDrag = true,
}) async {
  await tester.pumpWidget(
    MaterialApp(
      scrollBehavior: const NoScrollbarBehavior().copyWith(
        dragDevices: enableMouseDrag
            ? <ui.PointerDeviceKind>{...ui.PointerDeviceKind.values}
            : null,
        pointerAxisModifiers: axisModifier,
      ),
      theme: ThemeData(platform: platform),
      home: CustomScrollView(
        controller: controller,
        reverse: reverse,
        scrollDirection: scrollDirection,
        physics: scrollable ? null : const NeverScrollableScrollPhysics(),
        slivers: <Widget>[
          SliverToBoxAdapter(
            child: SizedBox(
              height: scrollDirection == Axis.vertical ? 2000.0 : null,
              width: scrollDirection == Axis.horizontal ? 2000.0 : null,
            ),
          ),
        ],
      ),
    ),
  );
  await tester.pump(const Duration(seconds: 5)); // to let the theme animate
}

class NoScrollbarBehavior extends MaterialScrollBehavior {
  const NoScrollbarBehavior();

  @override
  Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) => child;
}

// Pump a nested scrollable. The outer scrollable contains a sliver of a
// 300-pixel-long scrollable followed by a 2000-pixel-long content.
Future<void> pumpDoubleScrollableTest(WidgetTester tester, TargetPlatform platform) async {
  await tester.pumpWidget(
    MaterialApp(
      theme: ThemeData(platform: platform),
      home: const CustomScrollView(
        slivers: <Widget>[
          SliverToBoxAdapter(
            child: SizedBox(
              height: 300,
              child: CustomScrollView(
                slivers: <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
              ),
            ),
          ),
          SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
        ],
      ),
    ),
  );
  await tester.pump(const Duration(seconds: 5)); // to let the theme animate
}

const double dragOffset = 200.0;

double getScrollOffset(WidgetTester tester, {bool last = true}) {
  Finder viewportFinder = find.byType(Viewport);
  if (last) {
    viewportFinder = viewportFinder.last;
  }
  final RenderViewport viewport = tester.renderObject(viewportFinder);
  return viewport.offset.pixels;
}

double getScrollVelocity(WidgetTester tester) {
  final RenderViewport viewport = tester.renderObject(find.byType(Viewport));
  final position = viewport.offset as ScrollPosition;
  return position.activity!.velocity;
}

void resetScrollOffset(WidgetTester tester) {
  final RenderViewport viewport = tester.renderObject(find.byType(Viewport));
  final position = viewport.offset as ScrollPosition;
  position.jumpTo(0.0);
}

void main() {
  testWidgets('hitTestBehavior is respected', (WidgetTester tester) async {
    HitTestBehavior? getBehavior(Type of) {
      final RawGestureDetector widget = tester.widget(
        find.descendant(of: find.byType(of), matching: find.byType(RawGestureDetector)),
      );
      return widget.behavior;
    }

    await tester.pumpWidget(
      const MaterialApp(home: SingleChildScrollView(hitTestBehavior: HitTestBehavior.translucent)),
    );
    expect(getBehavior(SingleChildScrollView), HitTestBehavior.translucent);

    await tester.pumpWidget(
      const MaterialApp(home: CustomScrollView(hitTestBehavior: HitTestBehavior.translucent)),
    );
    expect(getBehavior(CustomScrollView), HitTestBehavior.translucent);

    await tester.pumpWidget(
      MaterialApp(home: ListView(hitTestBehavior: HitTestBehavior.translucent)),
    );
    expect(getBehavior(ListView), HitTestBehavior.translucent);

    await tester.pumpWidget(
      MaterialApp(
        home: GridView.extent(maxCrossAxisExtent: 1, hitTestBehavior: HitTestBehavior.translucent),
      ),
    );
    expect(getBehavior(GridView), HitTestBehavior.translucent);

    await tester.pumpWidget(
      MaterialApp(home: PageView(hitTestBehavior: HitTestBehavior.translucent)),
    );
    expect(getBehavior(PageView), HitTestBehavior.translucent);

    await tester.pumpWidget(
      MaterialApp(
        home: ListWheelScrollView(
          itemExtent: 10,
          hitTestBehavior: HitTestBehavior.translucent,
          children: const <Widget>[],
        ),
      ),
    );
    expect(getBehavior(ListWheelScrollView), HitTestBehavior.translucent);
  });

  testWidgets('hitTestBehavior.translucent lets widgets underneath catch the hit', (
    WidgetTester tester,
  ) async {
    final Key key = UniqueKey();
    var tapped = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Stack(
          children: <Widget>[
            Positioned.fill(
              child: GestureDetector(
                behavior: HitTestBehavior.opaque,
                onTap: () => tapped = true,
                child: SizedBox(key: key, height: 300),
              ),
            ),
            const SingleChildScrollView(hitTestBehavior: HitTestBehavior.translucent),
          ],
        ),
      ),
    );
    await tester.tapAt(tester.getCenter(find.byKey(key)));
    expect(tapped, isTrue);
  });

  testWidgets('Flings on different platforms', (WidgetTester tester) async {
    await pumpTest(tester, TargetPlatform.android);
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    expect(getScrollOffset(tester), dragOffset);
    await tester.pump(); // trigger fling
    expect(getScrollOffset(tester), dragOffset);
    await tester.pump(const Duration(seconds: 5));
    final double androidResult = getScrollOffset(tester);

    resetScrollOffset(tester);

    await pumpTest(tester, TargetPlatform.iOS);
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    // Scroll starts ease into the scroll on iOS.
    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
    await tester.pump(); // trigger fling
    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
    await tester.pump(const Duration(seconds: 5));
    final double iOSResult = getScrollOffset(tester);

    resetScrollOffset(tester);

    await pumpTest(tester, TargetPlatform.macOS);
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    // Scroll starts ease into the scroll on iOS.
    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
    await tester.pump(); // trigger fling
    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
    await tester.pump(const Duration(seconds: 5));
    final double macOSResult = getScrollOffset(tester);

    expect(macOSResult, lessThan(androidResult)); // macOS is slipperier than Android
    expect(androidResult, lessThan(iOSResult)); // iOS is slipperier than Android
    expect(macOSResult, lessThan(iOSResult)); // iOS is slipperier than macOS
  });

  testWidgets(
    'Holding scroll',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      await tester.drag(find.byType(Scrollable), const Offset(0.0, 200.0), touchSlopY: 0.0);
      expect(getScrollOffset(tester), -200.0);
      await tester.pump(); // trigger ballistic
      await tester.pump(const Duration(milliseconds: 10));
      expect(getScrollOffset(tester), greaterThan(-200.0));
      expect(getScrollOffset(tester), lessThan(0.0));
      final double heldPosition = getScrollOffset(tester);
      // Hold and let go while in overscroll.
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      expect(await tester.pumpAndSettle(), 1);
      expect(getScrollOffset(tester), heldPosition);
      await gesture.up();
      // Once the hold is let go, it should still snap back to origin.
      expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 3);
      expect(getScrollOffset(tester), 0.0);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'Repeated flings builds momentum',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump(); // trigger fling
      await tester.pump(const Duration(milliseconds: 10));
      // Repeat the exact same motion.
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump();
      // On iOS, the velocity will be larger than the velocity of the last fling by a
      // non-trivial amount.
      expect(getScrollVelocity(tester), greaterThan(1100.0));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets('Repeated flings do not build momentum on Android', (WidgetTester tester) async {
    await pumpTest(tester, TargetPlatform.android);
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    await tester.pump(); // trigger fling
    await tester.pump(const Duration(milliseconds: 10));
    // Repeat the exact same motion.
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    await tester.pump();
    // On Android, there is no momentum build. The final velocity is the same as the
    // velocity of the last fling.
    expect(getScrollVelocity(tester), moreOrLessEquals(1000.0));
  });

  testWidgets(
    'A slower final fling does not apply carried momentum',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump(); // trigger fling
      await tester.pump(const Duration(milliseconds: 10));
      // Repeat the exact same motion to build momentum.
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump(); // trigger the second fling
      await tester.pump(const Duration(milliseconds: 10));
      // Make a final fling that is much slower.
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 200.0);
      await tester.pump(); // trigger the third fling
      await tester.pump(const Duration(milliseconds: 10));
      // expect that there is no carried velocity
      expect(getScrollVelocity(tester), lessThan(200.0));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'No iOS/macOS momentum build with flings in opposite directions',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump(); // trigger fling
      await tester.pump(const Duration(milliseconds: 10));
      // Repeat the exact same motion in the opposite direction.
      await tester.fling(find.byType(Scrollable), const Offset(0.0, dragOffset), 1000.0);
      await tester.pump();
      // The only applied velocity to the scrollable is the second fling that was in the
      // opposite direction.
      expect(getScrollVelocity(tester), -1000.0);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'No iOS/macOS momentum kept on hold gestures',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
      await tester.pump(); // trigger fling
      await tester.pump(const Duration(milliseconds: 10));
      expect(getScrollVelocity(tester), greaterThan(0.0));
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      await tester.pump(const Duration(milliseconds: 40));
      await gesture.up();
      // After a hold longer than 2 frames, previous velocity is lost.
      expect(getScrollVelocity(tester), 0.0);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets('Drags creeping unaffected on Android', (WidgetTester tester) async {
    await pumpTest(tester, TargetPlatform.android);
    final TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
    );
    await gesture.moveBy(const Offset(0.0, -0.5));
    expect(getScrollOffset(tester), 0.5);
    await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 10));
    expect(getScrollOffset(tester), 1.0);
    await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 20));
    expect(getScrollOffset(tester), 1.5);
  });

  testWidgets(
    'Drags creeping must break threshold on iOS/macOS',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      await gesture.moveBy(const Offset(0.0, -0.5));
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 10));
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 20));
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 30));
      // Now -2.5 in total.
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 40));
      // Now -3.5, just reached threshold.
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 50));
      // -0.5 over threshold transferred.
      expect(getScrollOffset(tester), 0.5);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'Big drag over threshold magnitude preserved on iOS/macOS',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      await gesture.moveBy(const Offset(0.0, -30.0));
      // No offset lost from threshold.
      expect(getScrollOffset(tester), 30.0);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'Slow threshold breaks are attenuated on iOS/macOS',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      // This is a typical 'hesitant' iOS scroll start.
      await gesture.moveBy(const Offset(0.0, -10.0));
      expect(getScrollOffset(tester), moreOrLessEquals(1.1666666666666667));
      await gesture.moveBy(const Offset(0.0, -10.0), timeStamp: const Duration(milliseconds: 20));
      // Subsequent motions unaffected.
      expect(getScrollOffset(tester), moreOrLessEquals(11.16666666666666673));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'Small continuing motion preserved on iOS/macOS',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
      expect(getScrollOffset(tester), 30.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 20));
      expect(getScrollOffset(tester), 30.5);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 40));
      expect(getScrollOffset(tester), 31.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 60));
      expect(getScrollOffset(tester), 31.5);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets(
    'Motion stop resets threshold on iOS/macOS',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      );
      await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
      expect(getScrollOffset(tester), 30.0);
      await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 20));
      expect(getScrollOffset(tester), 30.5);
      await gesture.moveBy(Offset.zero, timeStamp: const Duration(milliseconds: 21));
      // Stationary too long, threshold reset.
      await gesture.moveBy(Offset.zero, timeStamp: const Duration(milliseconds: 120));
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 140));
      expect(getScrollOffset(tester), 30.5);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 150));
      expect(getScrollOffset(tester), 30.5);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 160));
      expect(getScrollOffset(tester), 30.5);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 170));
      // New threshold broken.
      expect(getScrollOffset(tester), 31.5);
      await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 180));
      expect(getScrollOffset(tester), 32.5);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets('Scroll pointer signals are handled on Fuchsia', (WidgetTester tester) async {
    await pumpTest(tester, TargetPlatform.fuchsia);
    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    expect(getScrollOffset(tester), 20.0);
    // Pointer signals should not cause overscroll.
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -30.0)));
    expect(getScrollOffset(tester), 0.0);
  });

  testWidgets('Scroll pointer signals are handled when there is competition', (
    WidgetTester tester,
  ) async {
    // This is a regression test. When there are multiple scrollables listening
    // to the same event, for example when scrollables are nested, there used
    // to be exceptions at scrolling events.

    await pumpDoubleScrollableTest(tester, TargetPlatform.fuchsia);
    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport).last);
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    expect(getScrollOffset(tester), 20.0);
    // Pointer signals should not cause overscroll.
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -30.0)));
    expect(getScrollOffset(tester), 0.0);
  });

  testWidgets('Scroll pointer signals are ignored when scrolling is disabled', (
    WidgetTester tester,
  ) async {
    await pumpTest(tester, TargetPlatform.fuchsia, scrollable: false);
    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    expect(getScrollOffset(tester), 0.0);
  });

  testWidgets(
    'Engine is notified of ignored pointer signals (no scroll physics)',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride, scrollable: false);
      final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
      final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
      // Create a hover event so that |testPointer| has a location when generating the scroll.
      testPointer.hover(scrollEventLocation);

      var allowedPlatformDefault = false;
      await tester.sendEventToBinding(
        testPointer.scroll(
          const Offset(0.0, 20.0),
          onRespond: ({required bool allowPlatformDefault}) {
            allowedPlatformDefault = allowPlatformDefault;
          },
        ),
      );

      expect(
        allowedPlatformDefault,
        isTrue,
        reason: 'Engine should be notified of ignored scroll pointer signals.',
      );
    },
    variant: TargetPlatformVariant.all(),
  );

  testWidgets('Engine is notified of accepted and rejected scroll events', (
    WidgetTester tester,
  ) async {
    await pumpTest(tester, debugDefaultTargetPlatformOverride, scrollDirection: Axis.horizontal);

    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);

    // Horizontal input is accepted
    var respondedAccepted = false;
    bool? allowPlatformDefaultAccepted;
    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    await tester.sendEventToBinding(
      testPointer.scroll(
        const Offset(0.0, 10.0),
        onRespond: ({required bool allowPlatformDefault}) {
          respondedAccepted = true;
          allowPlatformDefaultAccepted = allowPlatformDefault;
        },
      ),
    );
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pump();
    expect(respondedAccepted, isTrue, reason: 'Engine should be notified when scroll is accepted.');
    expect(
      allowPlatformDefaultAccepted,
      isFalse,
      reason: 'Accepted scroll should be reported as handled to the engine.',
    );

    // Vertical input not accepted
    var respondedRejected = false;
    var allowedPlatformDefault = false;
    await tester.sendEventToBinding(
      testPointer.scroll(
        const Offset(0.0, 20.0),
        onRespond: ({required bool allowPlatformDefault}) {
          respondedRejected = true;
          allowedPlatformDefault = allowPlatformDefault;
        },
      ),
    );
    expect(respondedRejected, isTrue, reason: 'Engine should be notified when scroll is rejected.');
    expect(
      allowedPlatformDefault,
      isTrue,
      reason: 'Engine should be notified when scroll is rejected by the scrollable.',
    );
  }, variant: TargetPlatformVariant.all());

  testWidgets(
    'Holding scroll and Scroll pointer signal will update ScrollDirection.forward / ScrollDirection.reverse',
    (WidgetTester tester) async {
      ScrollDirection? lastUserScrollingDirection;

      final controller = ScrollController();
      addTearDown(controller.dispose);

      await pumpTest(tester, TargetPlatform.fuchsia, controller: controller);

      controller.addListener(() {
        if (controller.position.userScrollDirection != ScrollDirection.idle) {
          lastUserScrollingDirection = controller.position.userScrollDirection;
        }
      });

      await tester.drag(find.byType(Scrollable), const Offset(0.0, -20.0), touchSlopY: 0.0);

      expect(lastUserScrollingDirection, ScrollDirection.reverse);

      final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
      final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
      // Create a hover event so that |testPointer| has a location when generating the scroll.
      testPointer.hover(scrollEventLocation);
      await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));

      expect(lastUserScrollingDirection, ScrollDirection.reverse);

      await tester.drag(find.byType(Scrollable), const Offset(0.0, 20.0), touchSlopY: 0.0);

      expect(lastUserScrollingDirection, ScrollDirection.forward);

      await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -20.0)));

      expect(lastUserScrollingDirection, ScrollDirection.forward);
    },
  );

  testWidgets('Scrolls in correct direction when scroll axis is reversed', (
    WidgetTester tester,
  ) async {
    await pumpTest(tester, TargetPlatform.fuchsia, reverse: true);

    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -20.0)));

    expect(getScrollOffset(tester), 20.0);
  });

  testWidgets('Scrolls horizontally when shift is pressed by default', (WidgetTester tester) async {
    await pumpTest(tester, debugDefaultTargetPlatformOverride, scrollDirection: Axis.horizontal);

    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 0.0);

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input flipped to horizontal and accepted.
    expect(getScrollOffset(tester), 20.0);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pump();

    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 20.0);
  }, variant: TargetPlatformVariant.all());

  testWidgets('Scroll axis is not flipped for trackpad', (WidgetTester tester) async {
    await pumpTest(tester, debugDefaultTargetPlatformOverride, scrollDirection: Axis.horizontal);

    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.trackpad);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 0.0);

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not flipped.
    expect(getScrollOffset(tester), 0.0);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pump();

    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 0.0);
  }, variant: TargetPlatformVariant.all());

  testWidgets('Scrolls horizontally when custom key is pressed', (WidgetTester tester) async {
    await pumpTest(
      tester,
      debugDefaultTargetPlatformOverride,
      scrollDirection: Axis.horizontal,
      axisModifier: <LogicalKeyboardKey>{LogicalKeyboardKey.altLeft},
    );

    final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 0.0);

    await tester.sendKeyDownEvent(LogicalKeyboardKey.altLeft);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input flipped to horizontal and accepted.
    expect(getScrollOffset(tester), 20.0);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.altLeft);
    await tester.pump();

    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    // Vertical input not accepted
    expect(getScrollOffset(tester), 20.0);
  }, variant: TargetPlatformVariant.all());

  testWidgets(
    'Still scrolls horizontally when other keys are pressed at the same time',
    (WidgetTester tester) async {
      await pumpTest(
        tester,
        debugDefaultTargetPlatformOverride,
        scrollDirection: Axis.horizontal,
        axisModifier: <LogicalKeyboardKey>{LogicalKeyboardKey.altLeft},
      );

      final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
      final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
      // Create a hover event so that |testPointer| has a location when generating the scroll.
      testPointer.hover(scrollEventLocation);
      await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
      // Vertical input not accepted
      expect(getScrollOffset(tester), 0.0);

      await tester.sendKeyDownEvent(LogicalKeyboardKey.altLeft);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.space);
      await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
      // Vertical flipped & accepted.
      expect(getScrollOffset(tester), 20.0);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.altLeft);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.space);
      await tester.pump();

      await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
      // Vertical input not accepted
      expect(getScrollOffset(tester), 20.0);
    },
    variant: TargetPlatformVariant.all(),
  );

  group('setCanDrag to false with active drag gesture: ', () {
    Future<void> pumpTestWidget(WidgetTester tester, {required bool canDrag}) {
      return tester.pumpWidget(
        MaterialApp(
          home: CustomScrollView(
            physics: canDrag
                ? const AlwaysScrollableScrollPhysics()
                : const NeverScrollableScrollPhysics(),
            slivers: <Widget>[
              SliverToBoxAdapter(
                child: SizedBox(height: 2000, child: GestureDetector(onTap: () {})),
              ),
            ],
          ),
        ),
      );
    }

    testWidgets('Hold does not disable user interaction', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/66816.
      await pumpTestWidget(tester, canDrag: true);
      final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
        find.descendant(of: find.byType(CustomScrollView), matching: find.byType(IgnorePointer)),
      );

      expect(renderIgnorePointer.ignoring, false);

      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Viewport)),
      );
      expect(renderIgnorePointer.ignoring, false);

      await pumpTestWidget(tester, canDrag: false);
      expect(renderIgnorePointer.ignoring, false);

      await gesture.up();
      expect(renderIgnorePointer.ignoring, false);
    });

    testWidgets('Drag disables user interaction when recognized', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/66816.
      await pumpTestWidget(tester, canDrag: true);
      final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
        find.descendant(of: find.byType(CustomScrollView), matching: find.byType(IgnorePointer)),
      );
      expect(renderIgnorePointer.ignoring, false);

      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Viewport)),
      );
      expect(renderIgnorePointer.ignoring, false);

      await gesture.moveBy(const Offset(0, -100));
      // Starts ignoring when the drag is recognized.
      expect(renderIgnorePointer.ignoring, true);

      await pumpTestWidget(tester, canDrag: false);
      expect(renderIgnorePointer.ignoring, false);

      await gesture.up();
      expect(renderIgnorePointer.ignoring, false);
    });

    testWidgets('Ballistic disables user interaction until it stops', (WidgetTester tester) async {
      await pumpTestWidget(tester, canDrag: true);
      final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
        find.descendant(of: find.byType(CustomScrollView), matching: find.byType(IgnorePointer)),
      );
      expect(renderIgnorePointer.ignoring, false);

      // Starts ignoring when the drag is recognized.
      await tester.fling(find.byType(Scrollable), const Offset(0, -100), 1000);
      expect(renderIgnorePointer.ignoring, true);
      await tester.pump();

      // When the activity ends we should stop ignoring pointers.
      await tester.pumpAndSettle();
      expect(renderIgnorePointer.ignoring, false);
    });
  });

  testWidgets('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async {
    final widgetTracker = <String>[];
    var cheapWidgets = 0;
    var expensiveWidgets = 0;
    final controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView.builder(
          controller: controller,
          itemBuilder: (BuildContext context, int index) {
            if (Scrollable.recommendDeferredLoadingForContext(context)) {
              cheapWidgets += 1;
              widgetTracker.add('cheap');
              return const SizedBox(height: 50.0);
            }
            widgetTracker.add('expensive');
            expensiveWidgets += 1;
            return const SizedBox(height: 50.0);
          },
        ),
      ),
    );

    await tester.pumpAndSettle();

    expect(expensiveWidgets, 17);
    expect(cheapWidgets, 0);

    // The position value here is different from the maximum velocity we will
    // reach, which is controlled by a combination of curve, duration, and
    // position.
    // This is just meant to be a pretty good simulation. A linear curve
    // with these same parameters will never back off on the velocity enough
    // to reset here.
    controller.animateTo(5000, duration: const Duration(seconds: 2), curve: Curves.linear);

    expect(expensiveWidgets, 17);
    expect(widgetTracker.every((String type) => type == 'expensive'), true);
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));
    expect(expensiveWidgets, 17);
    expect(cheapWidgets, 25);
    expect(widgetTracker.skip(17).every((String type) => type == 'cheap'), true);

    await tester.pumpAndSettle();

    expect(expensiveWidgets, 22);
    expect(cheapWidgets, 95);
    expect(widgetTracker.skip(17).skip(25).take(70).every((String type) => type == 'cheap'), true);
    expect(
      widgetTracker.skip(17).skip(25).skip(70).every((String type) => type == 'expensive'),
      true,
    );
  });

  testWidgets('Can recommendDeferredLoadingForContext - ballistics', (WidgetTester tester) async {
    var cheapWidgets = 0;
    var expensiveWidgets = 0;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            if (Scrollable.recommendDeferredLoadingForContext(context)) {
              cheapWidgets += 1;
              return const SizedBox(height: 50.0);
            }
            expensiveWidgets += 1;
            return SizedBox(key: ValueKey<String>('Box $index'), height: 50.0);
          },
        ),
      ),
    );

    await tester.pumpAndSettle();
    expect(find.byKey(const ValueKey<String>('Box 0')), findsOneWidget);
    expect(find.byKey(const ValueKey<String>('Box 52')), findsNothing);

    expect(expensiveWidgets, 17);
    expect(cheapWidgets, 0);

    // Getting the tester to simulate a life-like fling is difficult.
    // Instead, just manually drive the activity with a ballistic simulation as
    // if the user has flung the list.
    Scrollable.of(
      find.byType(SizedBox).evaluate().first,
    ).position.activity!.delegate.goBallistic(4000);

    await tester.pumpAndSettle();
    expect(find.byKey(const ValueKey<String>('Box 0')), findsNothing);
    expect(find.byKey(const ValueKey<String>('Box 52')), findsOneWidget);

    expect(expensiveWidgets, 40);
    expect(cheapWidgets, 21);
  });

  testWidgets('Can recommendDeferredLoadingForContext - override heuristic', (
    WidgetTester tester,
  ) async {
    var cheapWidgets = 0;
    var expensiveWidgets = 0;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView.builder(
          physics: SuperPessimisticScrollPhysics(),
          itemBuilder: (BuildContext context, int index) {
            if (Scrollable.recommendDeferredLoadingForContext(context)) {
              cheapWidgets += 1;
              return SizedBox(key: ValueKey<String>('Cheap box $index'), height: 50.0);
            }
            expensiveWidgets += 1;
            return SizedBox(key: ValueKey<String>('Box $index'), height: 50.0);
          },
        ),
      ),
    );
    await tester.pumpAndSettle();

    final ScrollPosition position = Scrollable.of(find.byType(SizedBox).evaluate().first).position;
    final physics = position.physics as SuperPessimisticScrollPhysics;

    expect(find.byKey(const ValueKey<String>('Box 0')), findsOneWidget);
    expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsNothing);

    expect(physics.count, 17);
    expect(expensiveWidgets, 17);
    expect(cheapWidgets, 0);

    // Getting the tester to simulate a life-like fling is difficult.
    // Instead, just manually drive the activity with a ballistic simulation as
    // if the user has flung the list.
    position.activity!.delegate.goBallistic(4000);

    await tester.pumpAndSettle();

    expect(find.byKey(const ValueKey<String>('Box 0')), findsNothing);
    expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsOneWidget);

    expect(expensiveWidgets, 17);
    expect(cheapWidgets, 44);
    expect(physics.count, 44 + 17);
  });

  testWidgets(
    'Can recommendDeferredLoadingForContext - override heuristic and always return true',
    (WidgetTester tester) async {
      var cheapWidgets = 0;
      var expensiveWidgets = 0;
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListView.builder(
            physics: const ExtraSuperPessimisticScrollPhysics(),
            itemBuilder: (BuildContext context, int index) {
              if (Scrollable.recommendDeferredLoadingForContext(context)) {
                cheapWidgets += 1;
                return SizedBox(key: ValueKey<String>('Cheap box $index'), height: 50.0);
              }
              expensiveWidgets += 1;
              return SizedBox(key: ValueKey<String>('Box $index'), height: 50.0);
            },
          ),
        ),
      );
      await tester.pumpAndSettle();

      final ScrollPosition position = Scrollable.of(
        find.byType(SizedBox).evaluate().first,
      ).position;

      expect(find.byKey(const ValueKey<String>('Cheap box 0')), findsOneWidget);
      expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsNothing);

      expect(expensiveWidgets, 0);
      expect(cheapWidgets, 17);

      // Getting the tester to simulate a life-like fling is difficult.
      // Instead, just manually drive the activity with a ballistic simulation as
      // if the user has flung the list.
      position.activity!.delegate.goBallistic(4000);

      await tester.pumpAndSettle();

      expect(find.byKey(const ValueKey<String>('Cheap box 0')), findsNothing);
      expect(find.byKey(const ValueKey<String>('Cheap box 52')), findsOneWidget);

      expect(expensiveWidgets, 0);
      expect(cheapWidgets, 61);
    },
  );

  testWidgets('ensureVisible does not move PageViews', (WidgetTester tester) async {
    final controller = PageController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: PageView(
          controller: controller,
          children: List<ListView>.generate(3, (int pageIndex) {
            return ListView(
              key: Key('list_$pageIndex'),
              children: List<Widget>.generate(100, (int listIndex) {
                return Row(
                  children: <Widget>[
                    Container(
                      key: Key('${pageIndex}_${listIndex}_0'),
                      color: Colors.red,
                      width: 200,
                      height: 10,
                    ),
                    Container(
                      key: Key('${pageIndex}_${listIndex}_1'),
                      color: Colors.blue,
                      width: 200,
                      height: 10,
                    ),
                    Container(
                      key: Key('${pageIndex}_${listIndex}_2'),
                      color: Colors.green,
                      width: 200,
                      height: 10,
                    ),
                  ],
                );
              }),
            );
          }),
        ),
      ),
    );

    final Finder targetMidRightPage0 = find.byKey(const Key('0_25_2'));
    final Finder targetMidRightPage1 = find.byKey(const Key('1_25_2'));
    final Finder targetMidLeftPage1 = find.byKey(const Key('1_25_0'));

    expect(find.byKey(const Key('list_0')), findsOneWidget);
    expect(find.byKey(const Key('list_1')), findsNothing);
    expect(targetMidRightPage0, findsOneWidget);
    expect(targetMidRightPage1, findsNothing);
    expect(targetMidLeftPage1, findsNothing);

    await tester.ensureVisible(targetMidRightPage0);
    await tester.pumpAndSettle();
    expect(targetMidRightPage0, findsOneWidget);
    expect(targetMidRightPage1, findsNothing);
    expect(targetMidLeftPage1, findsNothing);

    controller.jumpToPage(1);
    await tester.pumpAndSettle();

    expect(find.byKey(const Key('list_0')), findsNothing);
    expect(find.byKey(const Key('list_1')), findsOneWidget);
    await tester.ensureVisible(targetMidRightPage1);
    await tester.pumpAndSettle();

    expect(targetMidRightPage0, findsNothing);
    expect(targetMidRightPage1, findsOneWidget);
    expect(targetMidLeftPage1, findsOneWidget);

    await tester.ensureVisible(targetMidLeftPage1);
    await tester.pumpAndSettle();

    expect(targetMidRightPage0, findsNothing);
    expect(targetMidRightPage1, findsOneWidget);
    expect(targetMidLeftPage1, findsOneWidget);
  });

  testWidgets('ensureVisible does not move TabViews', (WidgetTester tester) async {
    final TickerProvider vsync = TestTickerProvider();
    final controller = TabController(length: 3, vsync: vsync);
    addTearDown(controller.dispose);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: TabBarView(
          controller: controller,
          children: List<ListView>.generate(3, (int pageIndex) {
            return ListView(
              key: Key('list_$pageIndex'),
              children: List<Widget>.generate(100, (int listIndex) {
                return Row(
                  children: <Widget>[
                    Container(
                      key: Key('${pageIndex}_${listIndex}_0'),
                      color: Colors.red,
                      width: 200,
                      height: 10,
                    ),
                    Container(
                      key: Key('${pageIndex}_${listIndex}_1'),
                      color: Colors.blue,
                      width: 200,
                      height: 10,
                    ),
                    Container(
                      key: Key('${pageIndex}_${listIndex}_2'),
                      color: Colors.green,
                      width: 200,
                      height: 10,
                    ),
                  ],
                );
              }),
            );
          }),
        ),
      ),
    );

    final Finder targetMidRightPage0 = find.byKey(const Key('0_25_2'));
    final Finder targetMidRightPage1 = find.byKey(const Key('1_25_2'));
    final Finder targetMidLeftPage1 = find.byKey(const Key('1_25_0'));

    expect(find.byKey(const Key('list_0')), findsOneWidget);
    expect(find.byKey(const Key('list_1')), findsNothing);
    expect(targetMidRightPage0, findsOneWidget);
    expect(targetMidRightPage1, findsNothing);
    expect(targetMidLeftPage1, findsNothing);

    await tester.ensureVisible(targetMidRightPage0);
    await tester.pumpAndSettle();
    expect(targetMidRightPage0, findsOneWidget);
    expect(targetMidRightPage1, findsNothing);
    expect(targetMidLeftPage1, findsNothing);

    controller.index = 1;
    await tester.pumpAndSettle();

    expect(find.byKey(const Key('list_0')), findsNothing);
    expect(find.byKey(const Key('list_1')), findsOneWidget);
    await tester.ensureVisible(targetMidRightPage1);
    await tester.pumpAndSettle();

    expect(targetMidRightPage0, findsNothing);
    expect(targetMidRightPage1, findsOneWidget);
    expect(targetMidLeftPage1, findsOneWidget);

    await tester.ensureVisible(targetMidLeftPage1);
    await tester.pumpAndSettle();

    expect(targetMidRightPage0, findsNothing);
    expect(targetMidRightPage1, findsOneWidget);
    expect(targetMidLeftPage1, findsOneWidget);
  });

  testWidgets('PointerScroll on nested NeverScrollable ListView goes to outer Scrollable.', (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/70948
    final outerController = ScrollController();
    addTearDown(outerController.dispose);
    final innerController = ScrollController();
    addTearDown(innerController.dispose);

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Scaffold(
          body: SingleChildScrollView(
            controller: outerController,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    for (int i = 0; i < 100; i++) Text('SingleChildScrollView $i'),
                  ],
                ),
                SizedBox(
                  height: 3000,
                  width: 400,
                  child: ListView.builder(
                    controller: innerController,
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount: 100,
                    itemBuilder: (BuildContext context, int index) {
                      return Text('Nested NeverScrollable ListView $index');
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
    expect(outerController.position.pixels, 0.0);
    expect(innerController.position.pixels, 0.0);
    final Offset outerScrollable = tester.getCenter(find.text('SingleChildScrollView 3'));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Hover over the outer scroll view and create a pointer scroll.
    testPointer.hover(outerScrollable);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 20.0)));
    await tester.pump(const Duration(milliseconds: 250));
    expect(outerController.position.pixels, 20.0);
    expect(innerController.position.pixels, 0.0);

    final Offset innerScrollable = tester.getCenter(
      find.text('Nested NeverScrollable ListView 20'),
    );
    // Hover over the inner scroll view and create a pointer scroll.
    // This inner scroll view is not scrollable, and so the outer should scroll.
    testPointer.hover(innerScrollable);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, -20.0)));
    await tester.pump(const Duration(milliseconds: 250));
    expect(outerController.position.pixels, 0.0);
    expect(innerController.position.pixels, 0.0);
  });

  // Regression test for https://github.com/flutter/flutter/issues/71949
  testWidgets('Zero offset pointer scroll should not trigger an assertion.', (
    WidgetTester tester,
  ) async {
    final controller = ScrollController();
    addTearDown(controller.dispose);

    Widget build(double height) {
      return MaterialApp(
        home: Scaffold(
          body: SizedBox(
            width: double.infinity,
            height: height,
            child: SingleChildScrollView(
              controller: controller,
              child: const SizedBox(width: double.infinity, height: 300.0),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(build(200.0));
    expect(controller.position.pixels, 0.0);

    controller.jumpTo(100.0);
    expect(controller.position.pixels, 100.0);

    // Make the outer constraints larger that the scrollable widget is no longer able to scroll.
    await tester.pumpWidget(build(300.0));
    expect(controller.position.pixels, 0.0);
    expect(controller.position.maxScrollExtent, 0.0);

    // Hover over the scroll view and create a zero offset pointer scroll.
    final Offset scrollable = tester.getCenter(find.byType(SingleChildScrollView));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    testPointer.hover(scrollable);
    await tester.sendEventToBinding(testPointer.scroll(Offset.zero));

    expect(tester.takeException(), null);
  });

  testWidgets(
    'Accepts drag with unknown device kind by default',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/90912.
      await tester.pumpWidget(
        const MaterialApp(
          home: CustomScrollView(
            slivers: <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
          ),
        ),
      );
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
        kind: ui.PointerDeviceKind.unknown,
      );
      expect(getScrollOffset(tester), 0.0);
      await gesture.moveBy(const Offset(0.0, -200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 200);

      await gesture.moveBy(const Offset(0.0, 200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 0.0);

      await gesture.removePointer();
      await tester.pump();
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
      TargetPlatform.android,
    }),
  );

  testWidgets(
    'Does not scroll with mouse pointer drag when behavior is configured to ignore them',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride, enableMouseDrag: false);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
        kind: ui.PointerDeviceKind.mouse,
      );

      await gesture.moveBy(const Offset(0.0, -200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 0.0);

      await gesture.moveBy(const Offset(0.0, 200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 0.0);

      await gesture.removePointer();
      await tester.pump();
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
      TargetPlatform.android,
    }),
  );

  testWidgets("Support updating 'ScrollBehavior.dragDevices' at runtime", (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/111716
    Widget buildFrame(Set<ui.PointerDeviceKind>? dragDevices) {
      return MaterialApp(
        scrollBehavior: const NoScrollbarBehavior().copyWith(dragDevices: dragDevices),
        home: ListView.builder(
          itemCount: 1000,
          itemBuilder: (BuildContext context, int index) {
            return Text('Item $index');
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(<ui.PointerDeviceKind>{ui.PointerDeviceKind.mouse}));
    await tester.drag(
      find.byType(Scrollable),
      const Offset(0.0, -100.0),
      kind: ui.PointerDeviceKind.mouse,
    );

    // Matching device should allow user scrolling.
    expect(getScrollOffset(tester), 100.0);

    await tester.pumpWidget(buildFrame(<ui.PointerDeviceKind>{ui.PointerDeviceKind.stylus}));
    await tester.drag(
      find.byType(Scrollable),
      const Offset(0.0, -100.0),
      kind: ui.PointerDeviceKind.mouse,
    );

    // Non-matching device should not allow user scrolling.
    expect(getScrollOffset(tester), 100.0);

    await tester.drag(
      find.byType(Scrollable),
      const Offset(0.0, -100.0),
      kind: ui.PointerDeviceKind.stylus,
    );

    // Matching device should allow user scrolling.
    expect(getScrollOffset(tester), 200.0);
  });

  testWidgets(
    'Does scroll with mouse pointer drag when behavior is not configured to ignore them',
    (WidgetTester tester) async {
      await pumpTest(tester, debugDefaultTargetPlatformOverride);
      final TestGesture gesture = await tester.startGesture(
        tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
        kind: ui.PointerDeviceKind.mouse,
      );

      await gesture.moveBy(const Offset(0.0, -200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 200.0);

      await gesture.moveBy(const Offset(0.0, 200));
      await tester.pump();
      await tester.pumpAndSettle();

      expect(getScrollOffset(tester), 0.0);

      await gesture.removePointer();
      await tester.pump();
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
      TargetPlatform.android,
    }),
  );

  testWidgets('Updated content dimensions correctly reflect in semantics', (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/40419.
    final SemanticsHandle handle = tester.ensureSemantics();
    final listView = UniqueKey();
    await tester.pumpWidget(
      MaterialApp(
        home: TickerMode(
          enabled: true,
          child: ListView.builder(
            key: listView,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return Text('Item $index');
            },
          ),
        ),
      ),
    );

    SemanticsNode scrollableNode = tester.getSemantics(
      find.descendant(of: find.byKey(listView), matching: find.byType(RawGestureDetector)),
    );
    SemanticsNode? syntheticScrollableNode;
    scrollableNode.visitChildren((SemanticsNode node) {
      syntheticScrollableNode = node;
      return true;
    });
    expect(syntheticScrollableNode!.hasFlag(ui.SemanticsFlag.hasImplicitScrolling), isTrue);
    // Disabled the ticker mode to trigger didChangeDependencies on Scrollable.
    // This can happen when a route is push or pop from top.
    // It will reconstruct the scroll position and apply content dimensions.
    await tester.pumpWidget(
      MaterialApp(
        home: TickerMode(
          enabled: false,
          child: ListView.builder(
            key: listView,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return Text('Item $index');
            },
          ),
        ),
      ),
    );
    await tester.pump();
    // The correct workflow will be the following:
    // 1. _RenderScrollSemantics receives a new scroll position without content
    //    dimensions and creates a SemanticsNode without implicit scroll.
    // 2. The content dimensions are applied to the scroll position during the
    //    layout phase, and the scroll position marks the semantics node of
    //    _RenderScrollSemantics dirty.
    // 3. The _RenderScrollSemantics rebuilds its semantics node with implicit
    //    scroll.
    scrollableNode = tester.getSemantics(
      find.descendant(of: find.byKey(listView), matching: find.byType(RawGestureDetector)),
    );
    syntheticScrollableNode = null;
    scrollableNode.visitChildren((SemanticsNode node) {
      syntheticScrollableNode = node;
      return true;
    });
    expect(syntheticScrollableNode!.hasFlag(ui.SemanticsFlag.hasImplicitScrolling), isTrue);
    handle.dispose();
  });

  testWidgets('Two panel semantics is added to the sibling nodes of direct children', (
    WidgetTester tester,
  ) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    final key = UniqueKey();
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: ListView(
            key: key,
            children: const <Widget>[
              TextField(autofocus: true, decoration: InputDecoration(prefixText: 'prefix')),
            ],
          ),
        ),
      ),
    );
    // Wait for focus.
    await tester.pumpAndSettle();

    final SemanticsNode scrollableNode = tester.getSemantics(find.byKey(key));
    SemanticsNode? intermediateNode;
    scrollableNode.visitChildren((SemanticsNode node) {
      intermediateNode = node;
      return true;
    });
    SemanticsNode? syntheticScrollableNode;
    intermediateNode!.visitChildren((SemanticsNode node) {
      syntheticScrollableNode = node;
      return true;
    });
    expect(syntheticScrollableNode!.hasFlag(ui.SemanticsFlag.hasImplicitScrolling), isTrue);

    var numberOfChild = 0;
    syntheticScrollableNode!.visitChildren((SemanticsNode node) {
      expect(node.isTagged(RenderViewport.useTwoPaneSemantics), isTrue);
      numberOfChild += 1;
      return true;
    });
    expect(numberOfChild, 2);

    handle.dispose();
  });

  testWidgets('Scroll inertia cancel event', (WidgetTester tester) async {
    await pumpTest(tester, null);
    await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
    expect(getScrollOffset(tester), dragOffset);
    await tester.pump(); // trigger fling
    expect(getScrollOffset(tester), dragOffset);
    await tester.pump(const Duration(milliseconds: 200));
    final testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    await tester.sendEventToBinding(testPointer.hover(tester.getCenter(find.byType(Scrollable))));
    await tester.sendEventToBinding(testPointer.scrollInertiaCancel()); // Cancel partway through.
    await tester.pump();
    expect(getScrollOffset(tester), closeTo(344.0642, 0.0001));
    await tester.pump(const Duration(milliseconds: 4800));
    expect(getScrollOffset(tester), closeTo(344.0642, 0.0001));
  });

  testWidgets('Swapping viewports in a scrollable does not crash', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);
    final GlobalKey key = GlobalKey();
    final GlobalKey key1 = GlobalKey();
    Widget buildScrollable(bool withViewPort) {
      return Scrollable(
        key: key,
        viewportBuilder: (BuildContext context, ViewportOffset position) {
          if (withViewPort) {
            final offset = ViewportOffset.zero();
            addTearDown(() => offset.dispose());
            return Viewport(
              slivers: <Widget>[
                SliverToBoxAdapter(
                  child: Semantics(key: key1, container: true, child: const Text('text1')),
                ),
              ],
              offset: offset,
            );
          }
          return Semantics(key: key1, container: true, child: const Text('text1'));
        },
      );
    }

    // This should cache the inner node in Scrollable with the children text1.
    await tester.pumpWidget(MaterialApp(home: buildScrollable(true)));
    expect(semantics, includesNodeWith(tags: <SemanticsTag>{RenderViewport.useTwoPaneSemantics}));
    // This does not use two panel, this should clear cached inner node.
    await tester.pumpWidget(MaterialApp(home: buildScrollable(false)));
    expect(
      semantics,
      isNot(includesNodeWith(tags: <SemanticsTag>{RenderViewport.useTwoPaneSemantics})),
    );
    // If the inner node was cleared in the previous step, this should not crash.
    await tester.pumpWidget(MaterialApp(home: buildScrollable(true)));
    expect(semantics, includesNodeWith(tags: <SemanticsTag>{RenderViewport.useTwoPaneSemantics}));
    expect(tester.takeException(), isNull);
    semantics.dispose();
  });

  testWidgets('deltaToScrollOrigin getter', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: CustomScrollView(
          slivers: <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
        ),
      ),
    );
    final TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.unknown,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pump();
    await tester.pumpAndSettle();

    expect(getScrollOffset(tester), 200);
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
    expect(scrollable.deltaToScrollOrigin, const Offset(0.0, 200));
  });

  testWidgets('resolvedPhysics getter', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: const CustomScrollView(
          physics: AlwaysScrollableScrollPhysics(),
          slivers: <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
        ),
      ),
    );
    final TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.unknown,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pump();
    await tester.pumpAndSettle();

    expect(getScrollOffset(tester), 200);
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
    String types(ScrollPhysics? value) => value!.parent == null
        ? '${value.runtimeType}'
        : '${value.runtimeType} ${types(value.parent)}';

    expect(
      types(scrollable.resolvedPhysics),
      'AlwaysScrollableScrollPhysics ClampingScrollPhysics RangeMaintainingScrollPhysics',
    );
  });

  testWidgets('dragDevices change updates widget', (WidgetTester tester) async {
    var enable = false;

    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          return StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MaterialApp(
                home: Scaffold(
                  body: Scrollable(
                    scrollBehavior: const MaterialScrollBehavior().copyWith(
                      dragDevices: <ui.PointerDeviceKind>{if (enable) ui.PointerDeviceKind.mouse},
                    ),
                    viewportBuilder: (BuildContext context, ViewportOffset position) => Viewport(
                      offset: position,
                      slivers: const <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
                    ),
                  ),
                  floatingActionButton: FloatingActionButton(
                    onPressed: () {
                      setState(() {
                        enable = !enable;
                      });
                    },
                  ),
                ),
              );
            },
          );
        },
      ),
    );

    // Gesture should not work.
    TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.mouse,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pumpAndSettle();
    expect(getScrollOffset(tester), 0.0);

    // Change state to include mouse pointer device.
    await tester.tap(find.byType(FloatingActionButton));
    await tester.pump();

    // Gesture should work after state change.
    gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.mouse,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pumpAndSettle();
    expect(getScrollOffset(tester), 200);
  });

  testWidgets('dragDevices change updates widget when oldWidget scrollBehavior is null', (
    WidgetTester tester,
  ) async {
    ScrollBehavior? scrollBehavior;

    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          return StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MaterialApp(
                home: Scaffold(
                  body: Scrollable(
                    physics: const ScrollPhysics(),
                    scrollBehavior: scrollBehavior,
                    viewportBuilder: (BuildContext context, ViewportOffset position) => Viewport(
                      offset: position,
                      slivers: const <Widget>[SliverToBoxAdapter(child: SizedBox(height: 2000.0))],
                    ),
                  ),
                  floatingActionButton: FloatingActionButton(
                    onPressed: () {
                      setState(() {
                        scrollBehavior = const MaterialScrollBehavior().copyWith(
                          dragDevices: <ui.PointerDeviceKind>{ui.PointerDeviceKind.mouse},
                        );
                      });
                    },
                  ),
                ),
              );
            },
          );
        },
      ),
    );

    // Gesture should not work.
    TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.mouse,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pumpAndSettle();
    expect(getScrollOffset(tester), 0.0);

    // Change state to include mouse pointer device.
    await tester.tap(find.byType(FloatingActionButton));
    await tester.pump();

    // Gesture should work after state change.
    gesture = await tester.startGesture(
      tester.getCenter(find.byType(Scrollable), warnIfMissed: true),
      kind: ui.PointerDeviceKind.mouse,
    );
    expect(getScrollOffset(tester), 0.0);
    await gesture.moveBy(const Offset(0.0, -200));
    await tester.pumpAndSettle();
    expect(getScrollOffset(tester), 200);
  });
}

// ignore: must_be_immutable
class SuperPessimisticScrollPhysics extends ScrollPhysics {
  SuperPessimisticScrollPhysics({super.parent});

  int count = 0;

  @override
  bool recommendDeferredLoading(double velocity, ScrollMetrics metrics, BuildContext context) {
    count++;
    return velocity > 1;
  }

  @override
  ScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return SuperPessimisticScrollPhysics(parent: buildParent(ancestor));
  }
}

class ExtraSuperPessimisticScrollPhysics extends ScrollPhysics {
  const ExtraSuperPessimisticScrollPhysics({super.parent});

  @override
  bool recommendDeferredLoading(double velocity, ScrollMetrics metrics, BuildContext context) {
    return true;
  }

  @override
  ScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return ExtraSuperPessimisticScrollPhysics(parent: buildParent(ancestor));
  }
}

class TestTickerProvider extends TickerProvider {
  @override
  Ticker createTicker(TickerCallback onTick) {
    return Ticker(onTick);
  }
}
