// 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/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../widgets/semantics_tester.dart';

const TextStyle testStyle = TextStyle(fontSize: 10.0, letterSpacing: 0.0);

void main() {
  testWidgets('Default layout minimum size', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(onPressed: null, child: Text('X', style: testStyle)),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(
      buttonBox.size,
      // 1 10px character + 20px * 2 = 50.0
      const Size(50.0, 44.0),
    );
  });

  testWidgets('Minimum size parameter', (WidgetTester tester) async {
    const minSize = 60.0;
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          onPressed: null,
          minSize: minSize,
          child: Text('X', style: testStyle),
        ),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(
      buttonBox.size,
      // 1 10px character + 20px * 2 = 50.0 (is smaller than minSize: 60.0)
      const Size.square(minSize),
    );
  });

  testWidgets('Minimum size minimumSize parameter', (WidgetTester tester) async {
    const size = Size(60.0, 100.0);
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(onPressed: null, minimumSize: size, child: SizedBox.shrink()),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(buttonBox.size, size);
  });

  testWidgets('Size grows with text', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(onPressed: null, child: Text('XXXX', style: testStyle)),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(
      buttonBox.size.width,
      // 4 10px character + 20px * 2 = 80.0
      80.0,
    );
  });

  testWidgets('OnLongPress works!', (WidgetTester tester) async {
    var value = false;
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          onPressed: null,
          onLongPress: () {
            value = !value;
          },
          child: const Text('XXXX', style: testStyle),
        ),
      ),
    );
    await tester.pump();
    final Finder cupertinoBtn = find.byType(CupertinoButton);
    await tester.longPress(cupertinoBtn);
    expect(value, isTrue);
  });

  testWidgets('button is disabled if onLongPress and onPressed are both null', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(onPressed: null, child: Text('XXXX', style: testStyle)),
      ),
    );

    expect(find.byType(CupertinoButton), findsOneWidget);
    final CupertinoButton button = tester.widget(find.byType(CupertinoButton));
    expect(button.enabled, isFalse);
  });

  // TODO(LongCatIsLoong): Uncomment once https://github.com/flutter/flutter/issues/44115
  // is fixed.
  /*
  testWidgets(
    'CupertinoButton.filled default color contrast meets guideline',
    (WidgetTester tester) async {
      // The native color combination systemBlue text over white background fails
      // to pass the color contrast guideline.
      //await tester.pumpWidget(
      //  CupertinoTheme(
      //    data: const CupertinoThemeData(),
      //    child: Directionality(
      //      textDirection: TextDirection.ltr,
      //      child: CupertinoButton.filled(
      //        child: const Text('Button'),
      //        onPressed: () {},
      //      ),
      //    ),
      //  ),
      //);
      //await expectLater(tester, meetsGuideline(textContrastGuideline));

      await tester.pumpWidget(
        CupertinoApp(
          theme: const CupertinoThemeData(brightness: Brightness.dark),
          home: CupertinoPageScaffold(
            child: CupertinoButton.filled(
              child: const Text('Button'),
              onPressed: () {},
            ),
          ),
        ),
      );

      await expectLater(tester, meetsGuideline(textContrastGuideline));
  });
  */

  testWidgets('Button child alignment', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton(onPressed: () {}, child: const Text('button')),
      ),
    );

    Align align = tester.firstWidget<Align>(
      find.ancestor(of: find.text('button'), matching: find.byType(Align)),
    );
    expect(align.alignment, Alignment.center); // default

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton(
          alignment: Alignment.centerLeft,
          onPressed: () {},
          child: const Text('button'),
        ),
      ),
    );

    align = tester.firstWidget<Align>(
      find.ancestor(of: find.text('button'), matching: find.byType(Align)),
    );
    expect(align.alignment, Alignment.centerLeft);
  });

  testWidgets('Button size changes depending on size property', (WidgetTester tester) async {
    const Widget child = Text('X', style: testStyle);

    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          onPressed: null,
          sizeStyle: CupertinoButtonSize.small,
          child: child,
        ),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(buttonBox.size, const Size(34.0, 28.0));

    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          onPressed: null,
          sizeStyle: CupertinoButtonSize.medium,
          child: child,
        ),
      ),
    );
    expect(buttonBox.size, const Size(40.0, 32.0));

    await tester.pumpWidget(
      boilerplate(child: const CupertinoButton(onPressed: null, child: child)),
    );
    expect(buttonBox.size, const Size(50.0, 44.0));
  });

  testWidgets('Custom padding', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          onPressed: null,
          padding: EdgeInsets.all(100.0),
          child: Text('X', style: testStyle),
        ),
      ),
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(buttonBox.size, const Size.square(210.0));
  });

  testWidgets('Button takes taps', (WidgetTester tester) async {
    var value = false;
    await tester.pumpWidget(
      StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) {
          return boilerplate(
            child: CupertinoButton(
              child: const Text('Tap me'),
              onPressed: () {
                setState(() {
                  value = true;
                });
              },
            ),
          );
        },
      ),
    );

    expect(value, isFalse);
    // No animating by default.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.tap(find.byType(CupertinoButton));
    expect(value, isTrue);
    // Animates.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
  });

  testWidgets("Disabled button doesn't animate", (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(child: const CupertinoButton(onPressed: null, child: Text('Tap me'))),
    );
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.tap(find.byType(CupertinoButton));
    // Still doesn't animate.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });

  testWidgets('Enabled button animates', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(child: const Text('Tap me'), onPressed: () {}),
      ),
    );

    await tester.tap(find.byType(CupertinoButton));
    // Enter animation.
    await tester.pump();
    FadeTransition transition = tester.firstWidget(find.byType(FadeTransition));

    await tester.pump(const Duration(milliseconds: 50));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(0.403, epsilon: 0.001));

    await tester.pump(const Duration(milliseconds: 100));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(0.400, epsilon: 0.001));

    await tester.pump(const Duration(milliseconds: 50));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(0.650, epsilon: 0.001));

    await tester.pump(const Duration(milliseconds: 50));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(0.894, epsilon: 0.001));

    await tester.pump(const Duration(milliseconds: 50));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(0.988, epsilon: 0.001));

    await tester.pump(const Duration(milliseconds: 50));
    transition = tester.firstWidget(find.byType(FadeTransition));
    expect(transition.opacity.value, moreOrLessEquals(1.0, epsilon: 0.001));
  });

  testWidgets('pressedOpacity defaults to 0.1', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(child: const Text('Tap me'), onPressed: () {}),
      ),
    );

    // Keep a "down" gesture on the button
    final Offset center = tester.getCenter(find.byType(CupertinoButton));
    final TestGesture gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    // Check opacity
    final FadeTransition opacity = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(FadeTransition)),
    );
    expect(opacity.opacity.value, 0.4);

    // Finish gesture to release resources.
    await gesture.up();
    await tester.pumpAndSettle();
  });

  testWidgets('pressedOpacity parameter', (WidgetTester tester) async {
    const pressedOpacity = 0.5;
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          pressedOpacity: pressedOpacity,
          child: const Text('Tap me'),
          onPressed: () {},
        ),
      ),
    );

    // Keep a "down" gesture on the button
    final Offset center = tester.getCenter(find.byType(CupertinoButton));
    final TestGesture gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    // Check opacity
    final FadeTransition opacity = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(FadeTransition)),
    );
    expect(opacity.opacity.value, pressedOpacity);

    // Finish gesture to release resources.
    await gesture.up();
    await tester.pumpAndSettle();
  });

  testWidgets('Cupertino button is semantically a button', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);
    await tester.pumpWidget(
      boilerplate(
        child: Center(
          child: CupertinoButton(onPressed: () {}, child: const Text('ABC')),
        ),
      ),
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              actions: SemanticsAction.tap.index | SemanticsAction.focus.index,
              label: 'ABC',
              flags: <SemanticsFlag>[SemanticsFlag.isButton, SemanticsFlag.isFocusable],
            ),
          ],
        ),
        ignoreId: true,
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    semantics.dispose();
  });

  testWidgets('Can specify colors', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          color: const Color(0x000000FF),
          disabledColor: const Color(0x0000FF00),
          onPressed: () {},
          child: const Text('Skeuomorph me'),
        ),
      ),
    );

    var decoration =
        tester.widget<DecoratedBox>(find.widgetWithText(DecoratedBox, 'Skeuomorph me')).decoration
            as ShapeDecoration;

    expect(decoration.color, const Color(0x000000FF));

    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          color: Color(0x000000FF),
          disabledColor: Color(0x0000FF00),
          onPressed: null,
          child: Text('Skeuomorph me'),
        ),
      ),
    );

    decoration =
        tester.widget<DecoratedBox>(find.widgetWithText(DecoratedBox, 'Skeuomorph me')).decoration
            as ShapeDecoration;

    expect(decoration.color, const Color(0x0000FF00));
  });

  testWidgets('Can specify dynamic colors', (WidgetTester tester) async {
    const Color bgColor = CupertinoDynamicColor.withBrightness(
      color: Color(0xFF123456),
      darkColor: Color(0xFF654321),
    );

    const Color inactive = CupertinoDynamicColor.withBrightness(
      color: Color(0xFF111111),
      darkColor: Color(0xFF222222),
    );

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(platformBrightness: Brightness.dark),
        child: boilerplate(
          child: CupertinoButton(
            color: bgColor,
            disabledColor: inactive,
            onPressed: () {},
            child: const Text('Skeuomorph me'),
          ),
        ),
      ),
    );

    var decoration =
        tester.widget<DecoratedBox>(find.widgetWithText(DecoratedBox, 'Skeuomorph me')).decoration
            as ShapeDecoration;

    expect(decoration.color!.value, 0xFF654321);

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(),
        child: boilerplate(
          child: const CupertinoButton(
            color: bgColor,
            disabledColor: inactive,
            onPressed: null,
            child: Text('Skeuomorph me'),
          ),
        ),
      ),
    );

    decoration =
        tester.widget<DecoratedBox>(find.widgetWithText(DecoratedBox, 'Skeuomorph me')).decoration
            as ShapeDecoration;

    // Disabled color.
    expect(decoration.color!.value, 0xFF111111);
  });

  testWidgets('Button respects themes', (WidgetTester tester) async {
    late TextStyle textStyle;

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, isSameColorAs(CupertinoColors.activeBlue));

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton.tinted(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, CupertinoColors.activeBlue);
    var decoration =
        tester
                .widget<DecoratedBox>(
                  find.descendant(
                    of: find.byType(CupertinoButton),
                    matching: find.byType(DecoratedBox),
                  ),
                )
                .decoration
            as ShapeDecoration;
    expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue.withOpacity(0.12)));

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton.filled(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, isSameColorAs(CupertinoColors.white));
    decoration =
        tester
                .widget<DecoratedBox>(
                  find.descendant(
                    of: find.byType(CupertinoButton),
                    matching: find.byType(DecoratedBox),
                  ),
                )
                .decoration
            as ShapeDecoration;
    expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue));

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoButton(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoButton.tinted(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
    decoration =
        tester
                .widget<DecoratedBox>(
                  find.descendant(
                    of: find.byType(CupertinoButton),
                    matching: find.byType(DecoratedBox),
                  ),
                )
                .decoration
            as ShapeDecoration;
    expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue.darkColor.withOpacity(0.26)));

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoButton.filled(
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );
    expect(textStyle.color, isSameColorAs(CupertinoColors.white));
    decoration =
        tester
                .widget<DecoratedBox>(
                  find.descendant(
                    of: find.byType(CupertinoButton),
                    matching: find.byType(DecoratedBox),
                  ),
                )
                .decoration
            as ShapeDecoration;
    expect(decoration.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton.filled(
          color: CupertinoColors.systemRed,
          onPressed: () {},
          child: Builder(
            builder: (BuildContext context) {
              textStyle = DefaultTextStyle.of(context).style;
              return const Placeholder();
            },
          ),
        ),
      ),
    );

    decoration =
        tester
                .widget<DecoratedBox>(
                  find.descendant(
                    of: find.byType(CupertinoButton),
                    matching: find.byType(DecoratedBox),
                  ),
                )
                .decoration
            as ShapeDecoration;
    expect(decoration.color, isSameColorAs(CupertinoColors.systemRed));
  });

  testWidgets("All CupertinoButton const maps keys' match the available style sizes", (
    WidgetTester tester,
  ) async {
    for (final CupertinoButtonSize size in CupertinoButtonSize.values) {
      expect(kCupertinoButtonPadding[size], isNotNull);
      expect(kCupertinoButtonSizeBorderRadius[size], isNotNull);
      expect(kCupertinoButtonMinSize[size], isNotNull);
    }
  });

  testWidgets('Hovering over Cupertino button updates cursor to clickable on Web', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoButton.filled(onPressed: () {}, child: const Text('Tap me')),
        ),
      ),
    );

    final TestGesture gesture = await tester.createGesture(
      kind: PointerDeviceKind.mouse,
      pointer: 1,
    );
    await gesture.addPointer(location: const Offset(10, 10));
    await tester.pumpAndSettle();
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      SystemMouseCursors.basic,
    );

    final Offset button = tester.getCenter(find.byType(CupertinoButton));
    await gesture.moveTo(button);
    await tester.pumpAndSettle();
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      kIsWeb ? SystemMouseCursors.click : SystemMouseCursors.basic,
    );
  });

  testWidgets('Button can be focused and has default colors', (WidgetTester tester) async {
    final focusNode = FocusNode(debugLabel: 'Button');
    addTearDown(focusNode.dispose);
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    final defaultFocusBorder = BorderSide(
      color: HSLColor.fromColor(CupertinoColors.activeBlue.withOpacity(kCupertinoFocusColorOpacity))
          .withLightness(kCupertinoFocusColorBrightness)
          .withSaturation(kCupertinoFocusColorSaturation)
          .toColor(),
      width: 3.5,
      strokeAlign: BorderSide.strokeAlignOutside,
    );

    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoButton(
            onPressed: () {},
            focusNode: focusNode,
            autofocus: true,
            child: const Text('Tap me'),
          ),
        ),
      ),
    );

    expect(focusNode.hasPrimaryFocus, isTrue);

    // The button has no border.
    expect(
      _findBorder(
        tester,
        find.descendant(of: find.byType(CupertinoButton), matching: find.byType(DecoratedBox)),
      ),
      BorderSide.none,
    );
    await tester.pump();

    // When focused, the button has a light blue border outline by default.
    focusNode.requestFocus();
    await tester.pumpAndSettle();
    expect(
      _findBorder(
        tester,
        find.descendant(of: find.byType(CupertinoButton), matching: find.byType(DecoratedBox)),
      ),
      defaultFocusBorder,
    );
  });

  testWidgets('Button configures focus color', (WidgetTester tester) async {
    final focusNode = FocusNode(debugLabel: 'Button');
    addTearDown(focusNode.dispose);

    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const Color focusColor = CupertinoColors.systemGreen;

    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoButton(
            onPressed: () {},
            focusNode: focusNode,
            autofocus: true,
            focusColor: focusColor,
            child: const Text('Tap me'),
          ),
        ),
      ),
    );

    expect(focusNode.hasPrimaryFocus, isTrue);
    focusNode.requestFocus();
    await tester.pump();
    await tester.pumpAndSettle();
    final BorderSide borderSide = _findBorder(
      tester,
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(DecoratedBox)),
    );
    expect(borderSide.color, focusColor);
  });

  testWidgets('CupertinoButton.onFocusChange callback', (WidgetTester tester) async {
    final focusNode = FocusNode(debugLabel: 'CupertinoButton');
    addTearDown(focusNode.dispose);

    var focused = false;
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoButton(
            onPressed: () {},
            focusNode: focusNode,
            onFocusChange: (bool value) {
              focused = value;
            },
            child: const Text('Tap me'),
          ),
        ),
      ),
    );

    focusNode.requestFocus();
    await tester.pump();
    expect(focused, isTrue);
    expect(focusNode.hasFocus, isTrue);

    focusNode.unfocus();
    await tester.pump();
    expect(focused, isFalse);
    expect(focusNode.hasFocus, isFalse);
  });

  testWidgets('IconThemeData falls back to default value when the TextStyle has a null size', (
    WidgetTester tester,
  ) async {
    const defaultIconTheme = IconThemeData(size: kCupertinoButtonDefaultIconSize);

    IconThemeData? actualIconTheme;

    // Large size.
    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(
          textTheme: CupertinoTextThemeData(actionTextStyle: TextStyle()),
        ),
        home: Center(
          child: CupertinoButton(
            onPressed: () {},
            child: Builder(
              builder: (BuildContext context) {
                actualIconTheme = IconTheme.of(context);

                return const Placeholder();
              },
            ),
          ),
        ),
      ),
    );
    expect(actualIconTheme?.size, defaultIconTheme.size);

    // Small size.
    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(
          textTheme: CupertinoTextThemeData(actionSmallTextStyle: TextStyle()),
        ),
        home: Center(
          child: CupertinoButton(
            onPressed: () {},
            child: Builder(
              builder: (BuildContext context) {
                actualIconTheme = IconTheme.of(context);

                return const Placeholder();
              },
            ),
          ),
        ),
      ),
    );
  });

  testWidgets('Button can be activated by keyboard shortcuts', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return CupertinoButton(
                onPressed: () {
                  setState(() {
                    value = !value;
                  });
                },
                autofocus: true,
                child: const Text('Tap me'),
              );
            },
          ),
        ),
      ),
    );
    await tester.pump();
    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pump();
    // On web, buttons don't respond to the enter key.
    expect(value, kIsWeb ? isTrue : isFalse);
    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pump();
    expect(value, isTrue);
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pump();
    expect(value, isFalse);
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pump();
    expect(value, isTrue);
  });

  testWidgets('Press and move on button and animation works', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(onPressed: () {}, child: const Text('Tap me')),
      ),
    );
    final TestGesture gesture = await tester.startGesture(
      tester.getTopLeft(find.byType(CupertinoButton)),
    );
    addTearDown(gesture.removePointer);
    // Check opacity.
    final FadeTransition opacity = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(FadeTransition)),
    );
    await tester.pumpAndSettle();
    expect(opacity.opacity.value, 0.4);
    final double moveDistance = CupertinoButton.tapMoveSlop();
    await gesture.moveBy(Offset(0, -moveDistance + 1));
    await tester.pumpAndSettle();
    expect(opacity.opacity.value, 0.4);
    await gesture.moveBy(const Offset(0, -2));
    await tester.pumpAndSettle();
    expect(opacity.opacity.value, 1.0);
    await gesture.moveBy(const Offset(0, 1));
    await tester.pumpAndSettle();
    expect(opacity.opacity.value, 0.4);
  }, variant: TargetPlatformVariant.all());

  testWidgets('Drag outside button within ListView does not leave the button pressed', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      boilerplate(
        child: ListView(
          children: <Widget>[CupertinoButton(onPressed: () {}, child: const Text('Tap me'))],
        ),
      ),
    );
    final FadeTransition opacity = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(FadeTransition)),
    );

    final TestGesture gesture = await tester.createGesture();
    addTearDown(gesture.removePointer);

    await gesture.down(tester.getTopLeft(find.byType(CupertinoButton)));
    await gesture.moveBy(const Offset(1, 1));
    await gesture.moveBy(Offset(0, -CupertinoButton.tapMoveSlop() - 5));
    await tester.pumpAndSettle();
    expect(opacity.opacity.value, 1.0);
  });

  testWidgets('onPressed trigger takes into account MoveSlop.', (WidgetTester tester) async {
    var value = false;
    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          onPressed: () {
            value = true;
          },
          child: const Text('Tap me'),
        ),
      ),
    );
    TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CupertinoButton)));
    await gesture.moveTo(
      tester.getBottomRight(find.byType(CupertinoButton)) +
          Offset(0, CupertinoButton.tapMoveSlop()),
    );
    await gesture.up();
    expect(value, isFalse);

    gesture = await tester.startGesture(tester.getTopLeft(find.byType(CupertinoButton)));
    await gesture.moveTo(
      tester.getBottomRight(find.byType(CupertinoButton)) +
          Offset(0, CupertinoButton.tapMoveSlop()),
    );
    await gesture.moveBy(const Offset(0, -1));
    await gesture.up();
    expect(value, isTrue);
  });

  testWidgets('Mouse cursor resolves in enabled/disabled/pressed/focused states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Button');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    addTearDown(focusNode.dispose);
    Widget buildButton({required bool enabled, MouseCursor? cursor}) {
      return CupertinoApp(
        home: Center(
          child: CupertinoButton(
            focusNode: focusNode,
            onPressed: enabled ? () {} : null,
            mouseCursor: cursor,
            child: const Text('Tap Me'),
          ),
        ),
      );
    }

    // Test default mouse cursor
    final TestGesture gesture = await tester.createGesture(
      kind: PointerDeviceKind.mouse,
      pointer: 1,
    );
    addTearDown(gesture.removePointer);
    await tester.pumpWidget(buildButton(enabled: true, cursor: const _ButtonMouseCursor()));
    await gesture.addPointer(location: tester.getCenter(find.byType(CupertinoButton)));
    await tester.pump();
    await gesture.moveTo(tester.getCenter(find.byType(CupertinoButton)));
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      SystemMouseCursors.basic,
    );

    // Test disabled state mouse cursor
    await tester.pumpWidget(buildButton(enabled: false, cursor: const _ButtonMouseCursor()));
    await gesture.moveTo(tester.getCenter(find.byType(CupertinoButton)));
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      SystemMouseCursors.forbidden,
    );

    // Test focused state mouse cursor
    await tester.pumpWidget(buildButton(enabled: true, cursor: const _ButtonMouseCursor()));
    focusNode.requestFocus();
    await tester.pump();
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      SystemMouseCursors.copy,
    );
    focusNode.unfocus();

    // Test pressed state mouse cursor
    await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.down(tester.getCenter(find.byType(CupertinoButton)));
    await tester.pump();
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      SystemMouseCursors.grab,
    );
    await gesture.up();
    await gesture.removePointer();
  });

  testWidgets('CupertinoButton foregroundColor applies to its text', (WidgetTester tester) async {
    const customForegroundColor = Color(0xFF5500FF);

    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          onPressed: () {},
          foregroundColor: customForegroundColor,
          child: const Text('Button'),
        ),
      ),
    );

    // Check that the text has the custom foreground color
    final RichText text = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(RichText)),
    );
    expect(text.text.style?.color, customForegroundColor);
  });

  testWidgets('CupertinoButton foregroundColor applies to its icon', (WidgetTester tester) async {
    const customForegroundColor = Color(0xFF5500FF);

    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton(
          onPressed: () {},
          foregroundColor: customForegroundColor,
          child: const Icon(IconData(0xE000)),
        ),
      ),
    );

    // Check that the icon has the custom foreground color
    final IconTheme iconTheme = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(IconTheme)),
    );
    expect(iconTheme.data.color, customForegroundColor);
  });

  testWidgets(
    "CupertinoButton uses the theme's primaryColor when foregroundColor is not specified",
    (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          home: Center(
            child: CupertinoButton(onPressed: () {}, child: const Text('Button')),
          ),
        ),
      );

      // The default color should be the primary color from the theme
      final BuildContext context = tester.element(find.text('Button'));
      final Color primaryColor = CupertinoTheme.of(context).primaryColor;

      final RichText text = tester.widget(find.byType(RichText));
      expect(text.text.style?.color, primaryColor);
    },
  );

  testWidgets('CupertinoButton.filled foregroundColor applies to its text', (
    WidgetTester tester,
  ) async {
    const customForegroundColor = Color(0xFF5500FF);

    await tester.pumpWidget(
      boilerplate(
        child: CupertinoButton.filled(
          onPressed: () {},
          foregroundColor: customForegroundColor,
          child: const Text('Button'),
        ),
      ),
    );

    // Check that the text has the custom foreground color
    final RichText text = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(RichText)),
    );
    expect(text.text.style?.color, customForegroundColor);
  });

  testWidgets('CupertinoButton foregroundColor applies to its text when disabled', (
    WidgetTester tester,
  ) async {
    const customForegroundColor = Color(0xFF5500FF);

    await tester.pumpWidget(
      boilerplate(
        child: const CupertinoButton(
          onPressed: null, // disabled button
          foregroundColor: customForegroundColor,
          child: Text('Button'),
        ),
      ),
    );

    // Check that the text has the custom foreground color even when disabled
    final RichText text = tester.widget(
      find.descendant(of: find.byType(CupertinoButton), matching: find.byType(RichText)),
    );
    expect(text.text.style?.color, customForegroundColor);
  });

  testWidgets('CupertinoButton does not crash at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: SizedBox.shrink(
            child: CupertinoButton(child: const Text('X'), onPressed: () {}),
          ),
        ),
      ),
    );
    expect(tester.getSize(find.byType(CupertinoButton)), Size.zero);
  });
}

Widget boilerplate({required Widget child}) {
  return Directionality(
    textDirection: TextDirection.ltr,
    child: Center(child: child),
  );
}

class _ButtonMouseCursor extends WidgetStateMouseCursor {
  const _ButtonMouseCursor();

  @override
  MouseCursor resolve(Set<WidgetState> states) {
    return const WidgetStateProperty<MouseCursor>.fromMap(<WidgetStatesConstraint, MouseCursor>{
      WidgetState.disabled: SystemMouseCursors.forbidden,
      WidgetState.pressed: SystemMouseCursors.grab,
      WidgetState.focused: SystemMouseCursors.copy,
      WidgetState.any: SystemMouseCursors.basic,
    }).resolve(states);
  }

  @override
  String get debugDescription => '_ButtonMouseCursor()';
}

BorderSide _findBorder(WidgetTester tester, Finder finder) {
  final decoration = tester.widget<DecoratedBox>(finder).decoration as ShapeDecoration;
  return (decoration.shape as RoundedSuperellipseBorder).side;
}
