// 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 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'semantics_tester.dart';

void main() {
  late bool tapped;
  late bool hovered;
  late Widget tapTarget;
  late Widget hoverTarget;
  late Animation<Color?> colorAnimation;

  setUp(() {
    tapped = false;
    colorAnimation = const AlwaysStoppedAnimation<Color?>(Colors.red);
    tapTarget = GestureDetector(
      onTap: () {
        tapped = true;
      },
      child: const SizedBox(
        width: 10.0,
        height: 10.0,
        child: Text('target', textDirection: TextDirection.ltr),
      ),
    );

    hovered = false;
    hoverTarget = MouseRegion(
      onHover: (_) { hovered = true; },
      onEnter: (_) { hovered = true; },
      onExit: (_) { hovered = true; },
      child: const SizedBox(
        width: 10.0,
        height: 10.0,
        child: Text('target', textDirection: TextDirection.ltr),
      ),
    );
  });

  group('ModalBarrier', () {
    testWidgets('prevents interactions with widgets behind it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          tapTarget,
          const ModalBarrier(dismissible: false),
        ],
      );

      await tester.pumpWidget(subject);
      await tester.tap(find.text('target'), warnIfMissed: false);
      await tester.pumpWidget(subject);
      expect(tapped, isFalse, reason: 'because the tap is not prevented by ModalBarrier');
    });

    testWidgets('prevents hover interactions with widgets behind it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          hoverTarget,
          const ModalBarrier(dismissible: false),
        ],
      );

      final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
      // Start out of hoverTarget
      await gesture.moveTo(const Offset(100, 100));

      await tester.pumpWidget(subject);
      // Move into hoverTarget and tap
      await gesture.down(const Offset(5, 5));
      await tester.pumpWidget(subject);
      await gesture.up();
      await tester.pumpWidget(subject);

      // Move out
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);

      expect(hovered, isFalse, reason: 'because the hover is not prevented by ModalBarrier');
    });

    testWidgets('does not prevent interactions with widgets in front of it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          const ModalBarrier(dismissible: false),
          tapTarget,
        ],
      );

      await tester.pumpWidget(subject);
      await tester.tap(find.text('target'));
      await tester.pumpWidget(subject);
      expect(tapped, isTrue, reason: 'because the tap is prevented by ModalBarrier');
    });

    testWidgets('does not prevent interactions with translucent widgets in front of it', (WidgetTester tester) async {
      bool dragged = false;
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          const ModalBarrier(dismissible: false),
          GestureDetector(
            behavior: HitTestBehavior.translucent,
            onHorizontalDragStart: (_) {
              dragged = true;
            },
            child: const Center(
              child: Text('target', textDirection: TextDirection.ltr),
            ),
          ),
        ],
      );

      await tester.pumpWidget(subject);
      await tester.dragFrom(
        tester.getBottomRight(find.byType(GestureDetector)) - const Offset(10, 10),
        const Offset(-20, 0),
      );
      await tester.pumpWidget(subject);
      expect(dragged, isTrue, reason: 'because the drag is prevented by ModalBarrier');
    });

    testWidgets('does not prevent hover interactions with widgets in front of it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          const ModalBarrier(dismissible: false),
          hoverTarget,
        ],
      );

      final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
      // Start out of hoverTarget
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);
      expect(hovered, isFalse);

      // Move into hoverTarget
      await gesture.moveTo(const Offset(5, 5));
      await tester.pumpWidget(subject);
      expect(hovered, isTrue, reason: 'because the hover is prevented by ModalBarrier');
      hovered = false;

      // Move out
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);
      expect(hovered, isTrue, reason: 'because the hover is prevented by ModalBarrier');
      hovered = false;
    });

    testWidgets('plays system alert sound when user tries to dismiss it', (WidgetTester tester) async {
      final List<String> playedSystemSounds = <String>[];
      try {
        tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
            SystemChannels.platform, (MethodCall methodCall) async {
          if (methodCall.method == 'SystemSound.play') {
            playedSystemSounds.add(methodCall.arguments as String);
          }
          return null;
        });

        final Widget subject = Stack(
          textDirection: TextDirection.ltr,
          children: <Widget>[
            tapTarget,
            const ModalBarrier(dismissible: false),
          ],
        );

        await tester.pumpWidget(subject);
        await tester.tap(find.text('target'), warnIfMissed: false);
        await tester.pumpWidget(subject);
      } finally {
        tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
      }
      expect(playedSystemSounds, hasLength(1));
      expect(playedSystemSounds[0], SystemSoundType.alert.toString());
    });

    testWidgets('pops the Navigator when dismissed by primary tap', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const SecondWidget(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Press the barrier; it shouldn't dismiss yet
      final TestGesture gesture = await tester.press(
        find.byKey(const ValueKey<String>('barrier')),
      );
      await tester.pumpAndSettle(); // begin transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Release the pointer; the barrier should be dismissed
      await gesture.up();
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('pops the Navigator when dismissed by non-primary tap', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const SecondWidget(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Press the barrier; it shouldn't dismiss yet
      final TestGesture gesture = await tester.press(
        find.byKey(const ValueKey<String>('barrier')),
        buttons: kSecondaryButton,
      );
      await tester.pumpAndSettle(); // begin transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Release the pointer; the barrier should be dismissed
      await gesture.up();
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('may pop the Navigator when competing with other gestures', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const SecondWidgetWithCompetence(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Tap on the barrier to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('does not pop the Navigator with a WillPopScope that returns false', (WidgetTester tester) async {
      bool willPopCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            Stack(
              children: <Widget>[
                const SecondWidget(),
                WillPopScope(
                  child: const SizedBox(),
                  onWillPop: () async {
                    willPopCalled = true;
                    return false;
                  },
                ),
              ],
            ),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(willPopCalled, isFalse);

      // Tap on the barrier to attempt to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsOneWidget,
        reason: 'The route should still be present if the pop is vetoed.',
      );

      expect(willPopCalled, isTrue);
    });

    testWidgets('pops the Navigator with a WillPopScope that returns true', (WidgetTester tester) async {
      bool willPopCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            Stack(
              children: <Widget>[
                const SecondWidget(),
                WillPopScope(
                  child: const SizedBox(),
                  onWillPop: () async {
                    willPopCalled = true;
                    return true;
                  },
                ),
              ],
            ),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(willPopCalled, isFalse);

      // Tap on the barrier to attempt to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should not be present if the pop is permitted.',
      );

      expect(willPopCalled, isTrue);
    });

    testWidgets('will call onDismiss callback', (WidgetTester tester) async {
      bool dismissCallbackCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            SecondWidget(onDismiss: () {
              dismissCallbackCalled = true;
            }),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);
      expect(dismissCallbackCalled, false);

      // Tap on the barrier
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(dismissCallbackCalled, true);
    });

    testWidgets('will not pop when given an onDismiss callback', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => SecondWidget(onDismiss: () {}),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Tap on the barrier
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsOneWidget,
        reason: 'The route should not have been dismissed by tapping the barrier, as there was a onDismiss callback given.',
      );
    });

    testWidgets('Undismissible ModalBarrier hidden in semantic tree', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(const ModalBarrier(dismissible: false));

      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));

      semantics.dispose();
    });

    testWidgets('Dismissible ModalBarrier includes button in semantic tree on iOS', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(const Directionality(
        textDirection: TextDirection.ltr,
        child: ModalBarrier(
          semanticsLabel: 'Dismiss',
        ),
      ));

      final TestSemantics expectedSemantics = TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            rect: TestSemantics.fullScreen,
            actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
            label: 'Dismiss',
            textDirection: TextDirection.ltr,
          ),
        ],
      );
      expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));

      semantics.dispose();
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS}));

    testWidgets(
        'Dismissible ModalBarrier is hidden on Android (back button is used to dismiss)', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(const ModalBarrier());

      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));

      semantics.dispose();
    });
  });
  group('AnimatedModalBarrier', () {
    testWidgets('prevents interactions with widgets behind it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          tapTarget,
          AnimatedModalBarrier(dismissible: false, color: colorAnimation),
        ],
      );

      await tester.pumpWidget(subject);
      await tester.tap(find.text('target'), warnIfMissed: false);
      await tester.pumpWidget(subject);
      expect(tapped, isFalse, reason: 'because the tap is not prevented by ModalBarrier');
    });

    testWidgets('prevents hover interactions with widgets behind it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          hoverTarget,
          AnimatedModalBarrier(dismissible: false, color: colorAnimation),
        ],
      );

      final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
      // Start out of hoverTarget
      await gesture.moveTo(const Offset(100, 100));

      await tester.pumpWidget(subject);
      // Move into hoverTarget and tap
      await gesture.down(const Offset(5, 5));
      await tester.pumpWidget(subject);
      await gesture.up();
      await tester.pumpWidget(subject);

      // Move out
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);

      expect(hovered, isFalse, reason: 'because the hover is not prevented by AnimatedModalBarrier');
    });

    testWidgets('does not prevent interactions with widgets in front of it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          AnimatedModalBarrier(dismissible: false, color: colorAnimation),
          tapTarget,
        ],
      );

      await tester.pumpWidget(subject);
      await tester.tap(find.text('target'));
      await tester.pumpWidget(subject);
      expect(tapped, isTrue, reason: 'because the tap is prevented by AnimatedModalBarrier');
    });

    testWidgets('does not prevent interactions with translucent widgets in front of it', (WidgetTester tester) async {
      bool dragged = false;
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          AnimatedModalBarrier(dismissible: false, color: colorAnimation),
          GestureDetector(
            behavior: HitTestBehavior.translucent,
            onHorizontalDragStart: (_) {
              dragged = true;
            },
            child: const Center(
              child: Text('target', textDirection: TextDirection.ltr),
            ),
          ),
        ],
      );

      await tester.pumpWidget(subject);
      await tester.dragFrom(
        tester.getBottomRight(find.byType(GestureDetector)) - const Offset(10, 10),
        const Offset(-20, 0),
      );
      await tester.pumpWidget(subject);
      expect(dragged, isTrue, reason: 'because the drag is prevented by AnimatedModalBarrier');
    });

    testWidgets('does not prevent hover interactions with widgets in front of it', (WidgetTester tester) async {
      final Widget subject = Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          AnimatedModalBarrier(dismissible: false, color: colorAnimation),
          hoverTarget,
        ],
      );

      final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
      // Start out of hoverTarget
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);
      expect(hovered, isFalse);

      // Move into hoverTarget
      await gesture.moveTo(const Offset(5, 5));
      await tester.pumpWidget(subject);
      expect(hovered, isTrue, reason: 'because the hover is prevented by AnimatedModalBarrier');
      hovered = false;

      // Move out
      await gesture.moveTo(const Offset(100, 100));
      await tester.pumpWidget(subject);
      expect(hovered, isTrue, reason: 'because the hover is prevented by AnimatedModalBarrier');
      hovered = false;
    });

    testWidgets('plays system alert sound when user tries to dismiss it', (WidgetTester tester) async {
      final List<String> playedSystemSounds = <String>[];
      try {
        tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
            SystemChannels.platform, (MethodCall methodCall) async {
          if (methodCall.method == 'SystemSound.play') {
            playedSystemSounds.add(methodCall.arguments as String);
          }
          return null;
        });

        final Widget subject = Stack(
          textDirection: TextDirection.ltr,
          children: <Widget>[
            tapTarget,
            AnimatedModalBarrier(dismissible: false, color: colorAnimation),
          ],
        );

        await tester.pumpWidget(subject);
        await tester.tap(find.text('target'), warnIfMissed: false);
        await tester.pumpWidget(subject);
      } finally {
        tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
      }
      expect(playedSystemSounds, hasLength(1));
      expect(playedSystemSounds[0], SystemSoundType.alert.toString());
    });

    testWidgets('pops the Navigator when dismissed by primary tap', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const AnimatedSecondWidget(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Press the barrier; it shouldn't dismiss yet
      final TestGesture gesture = await tester.press(
        find.byKey(const ValueKey<String>('barrier')),
      );
      await tester.pumpAndSettle(); // begin transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Release the pointer; the barrier should be dismissed
      await gesture.up();
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('pops the Navigator when dismissed by non-primary tap', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const AnimatedSecondWidget(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Press the barrier; it shouldn't dismiss yet
      final TestGesture gesture = await tester.press(
        find.byKey(const ValueKey<String>('barrier')),
        buttons: kSecondaryButton,
      );
      await tester.pumpAndSettle(); // begin transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Release the pointer; the barrier should be dismissed
      await gesture.up();
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('may pop the Navigator when competing with other gestures', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => const AnimatedSecondWidgetWithCompetence(),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      // Tap on the barrier to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should have been dismissed by tapping the barrier.',
      );
    });

    testWidgets('does not pop the Navigator with a WillPopScope that returns false', (WidgetTester tester) async {
      bool willPopCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            Stack(
              children: <Widget>[
                const AnimatedSecondWidget(),
                WillPopScope(
                  child: const SizedBox(),
                  onWillPop: () async {
                    willPopCalled = true;
                    return false;
                  },
                ),
              ],
            ),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(willPopCalled, isFalse);

      // Tap on the barrier to attempt to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsOneWidget,
        reason: 'The route should still be present if the pop is vetoed.',
      );

      expect(willPopCalled, isTrue);
    });

    testWidgets('pops the Navigator with a WillPopScope that returns true', (WidgetTester tester) async {
      bool willPopCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            Stack(
              children: <Widget>[
                const AnimatedSecondWidget(),
                WillPopScope(
                  child: const SizedBox(),
                  onWillPop: () async {
                    willPopCalled = true;
                    return true;
                  },
                ),
              ],
            ),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(willPopCalled, isFalse);

      // Tap on the barrier to attempt to dismiss it
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition

      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsNothing,
        reason: 'The route should not be present if the pop is permitted.',
      );

      expect(willPopCalled, isTrue);
    });

    testWidgets('will call onDismiss callback', (WidgetTester tester) async {
      bool dismissCallbackCalled = false;
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) =>
            AnimatedSecondWidget(onDismiss: () {
              dismissCallbackCalled = true;
            }),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);
      expect(dismissCallbackCalled, false);

      // Tap on the barrier
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(dismissCallbackCalled, true);
    });

    testWidgets('will not pop when given an onDismiss callback', (WidgetTester tester) async {
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (BuildContext context) => const FirstWidget(),
        '/modal': (BuildContext context) => AnimatedSecondWidget(onDismiss: () {}),
      };

      await tester.pumpWidget(MaterialApp(routes: routes));

      // Initially the barrier is not visible
      expect(find.byKey(const ValueKey<String>('barrier')), findsNothing);

      // Tapping on X routes to the barrier
      await tester.tap(find.text('X'));
      await tester.pump(); // begin transition
      await tester.pump(const Duration(seconds: 1)); // end transition
      expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);

      // Tap on the barrier
      await tester.tap(find.byKey(const ValueKey<String>('barrier')));
      await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
      expect(
        find.byKey(const ValueKey<String>('barrier')),
        findsOneWidget,
        reason: 'The route should not have been dismissed by tapping the barrier, as there was a onDismiss callback given.',
      );
    });

    testWidgets('Undismissible AnimatedModalBarrier hidden in semantic tree', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(AnimatedModalBarrier(dismissible: false, color: colorAnimation));

      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));

      semantics.dispose();
    });

    testWidgets('Dismissible AnimatedModalBarrier includes button in semantic tree on iOS', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: AnimatedModalBarrier(
          semanticsLabel: 'Dismiss',
          color: colorAnimation,
        ),
      ));

      final TestSemantics expectedSemantics = TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            rect: TestSemantics.fullScreen,
            actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
            label: 'Dismiss',
            textDirection: TextDirection.ltr,
          ),
        ],
      );
      expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));

      semantics.dispose();
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS}));

    testWidgets(
        'Dismissible AnimatedModalBarrier is hidden on Android (back button is used to dismiss)', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(AnimatedModalBarrier(color: colorAnimation));

      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));

      semantics.dispose();
    });
  });

  testWidgets('uses default mouse cursor', (WidgetTester tester) async {
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: const <Widget>[
        MouseRegion(cursor: SystemMouseCursors.click),
        ModalBarrier(dismissible: false),
      ],
    ));

    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
    await gesture.addPointer(location: tester.getCenter(find.byType(ModalBarrier)));

    await tester.pump();

    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
  });
}

class FirstWidget extends StatelessWidget {
  const FirstWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.pushNamed(context, '/modal');
      },
      child: const Text('X'),
    );
  }
}

class SecondWidget extends StatelessWidget {
  const SecondWidget({super.key, this.onDismiss});

  final VoidCallback? onDismiss;

  @override
  Widget build(BuildContext context) {
    return ModalBarrier(
      key: const ValueKey<String>('barrier'),
      onDismiss: onDismiss,
    );
  }
}

class AnimatedSecondWidget extends StatelessWidget {
  const AnimatedSecondWidget({super.key, this.onDismiss});

  final VoidCallback? onDismiss;

  @override
  Widget build(BuildContext context) {
    return AnimatedModalBarrier(
      key: const ValueKey<String>('barrier'),
      color: const AlwaysStoppedAnimation<Color?>(Colors.red),
      onDismiss: onDismiss,
    );
  }
}

class SecondWidgetWithCompetence extends StatelessWidget {
  const SecondWidgetWithCompetence({super.key});
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        const ModalBarrier(
          key: ValueKey<String>('barrier'),
        ),
        GestureDetector(
          onVerticalDragStart: (_) {},
          behavior: HitTestBehavior.translucent,
          child: Container(),
        ),
      ],
    );
  }
}
class AnimatedSecondWidgetWithCompetence extends StatelessWidget {
  const AnimatedSecondWidgetWithCompetence({super.key});
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        const AnimatedModalBarrier(
          key: ValueKey<String>('barrier'),
          color: AlwaysStoppedAnimation<Color?>(Colors.red),
        ),
        GestureDetector(
          onVerticalDragStart: (_) {},
          behavior: HitTestBehavior.translucent,
          child: Container(),
        ),
      ],
    );
  }
}
