// 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.

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;

import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/src/gestures/constants.dart';
import 'package:flutter_test/flutter_test.dart';

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

void main() {
  final theme = ThemeData();

  testWidgets('Radio control test', (WidgetTester tester) async {
    final Key key = UniqueKey();
    final log = <int?>[];

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(key: key, value: 1, groupValue: 2, onChanged: log.add),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, equals(<int>[1]));
    log.clear();

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(
              key: key,
              value: 1,
              groupValue: 1,
              onChanged: log.add,
              activeColor: Colors.green[500],
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, isEmpty);

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(child: Radio<int>(key: key, value: 1, groupValue: 2)),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, isEmpty);
  });

  testWidgets('Radio disabled', (WidgetTester tester) async {
    final Key key = UniqueKey();
    final log = <int?>[];

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(
              key: key,
              value: 1,
              groupValue: 2,
              enabled: false,
              onChanged: log.add,
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, equals(<int>[]));
  });

  testWidgets('Radio can be toggled when toggleable is set', (WidgetTester tester) async {
    final Key key = UniqueKey();
    final log = <int?>[];

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(
              key: key,
              value: 1,
              groupValue: 2,
              onChanged: log.add,
              toggleable: true,
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, equals(<int>[1]));
    log.clear();

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(
              key: key,
              value: 1,
              groupValue: 1,
              onChanged: log.add,
              toggleable: true,
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, equals(<int?>[null]));
    log.clear();

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Center(
            child: Radio<int>(key: key, value: 1, onChanged: log.add, toggleable: true),
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));

    expect(log, equals(<int>[1]));
  });

  testWidgets('Radio size is configurable by ThemeData.materialTapTargetSize', (
    WidgetTester tester,
  ) async {
    final Key key1 = UniqueKey();
    await tester.pumpWidget(
      Theme(
        data: theme.copyWith(materialTapTargetSize: MaterialTapTargetSize.padded),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: Radio<bool>(
                key: key1,
                groupValue: true,
                value: true,
                onChanged: (bool? newValue) {},
              ),
            ),
          ),
        ),
      ),
    );

    expect(tester.getSize(find.byKey(key1)), const Size(48.0, 48.0));

    final Key key2 = UniqueKey();
    await tester.pumpWidget(
      Theme(
        data: theme.copyWith(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: Radio<bool>(
                key: key2,
                groupValue: true,
                value: true,
                onChanged: (bool? newValue) {},
              ),
            ),
          ),
        ),
      ),
    );

    expect(tester.getSize(find.byKey(key2)), const Size(40.0, 40.0));
  });

  testWidgets('Radio selected semantics - platform adaptive', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(child: Radio<int>(value: 1, groupValue: 1, onChanged: (int? i) {})),
      ),
    );
    final bool isCupertino =
        defaultTargetPlatform == TargetPlatform.iOS ||
        defaultTargetPlatform == TargetPlatform.macOS;
    expect(
      semantics,
      includesNodeWith(
        flags: <SemanticsFlag>[
          SemanticsFlag.isInMutuallyExclusiveGroup,
          SemanticsFlag.hasCheckedState,
          SemanticsFlag.hasEnabledState,
          SemanticsFlag.isEnabled,
          SemanticsFlag.isFocusable,
          SemanticsFlag.isChecked,
          if (isCupertino) SemanticsFlag.hasSelectedState,
          if (isCupertino) SemanticsFlag.isSelected,
        ],
        actions: <SemanticsAction>[
          SemanticsAction.tap,
          if (defaultTargetPlatform != TargetPlatform.iOS) SemanticsAction.focus,
        ],
      ),
    );
    semantics.dispose();
  }, variant: TargetPlatformVariant.all());

  testWidgets('Radio semantics', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(child: Radio<int>(value: 1, groupValue: 2, onChanged: (int? i) {})),
      ),
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              id: 1,
              flags: <SemanticsFlag>[
                SemanticsFlag.isInMutuallyExclusiveGroup,
                SemanticsFlag.hasCheckedState,
                SemanticsFlag.hasEnabledState,
                SemanticsFlag.isEnabled,
                SemanticsFlag.isFocusable,
              ],
              actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(child: Radio<int>(value: 2, groupValue: 2, onChanged: (int? i) {})),
      ),
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              id: 1,
              flags: <SemanticsFlag>[
                SemanticsFlag.isInMutuallyExclusiveGroup,
                SemanticsFlag.hasCheckedState,
                SemanticsFlag.isChecked,
                SemanticsFlag.hasEnabledState,
                SemanticsFlag.isEnabled,
                SemanticsFlag.isFocusable,
              ],
              actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: const Material(child: Radio<int>(value: 1, groupValue: 2)),
      ),
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              id: 1,
              flags: <SemanticsFlag>[
                SemanticsFlag.hasCheckedState,
                SemanticsFlag.hasEnabledState,
                SemanticsFlag.isInMutuallyExclusiveGroup,
                SemanticsFlag.isFocusable, // This flag is delayed by 1 frame.
              ],
              actions: <SemanticsAction>[SemanticsAction.focus],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    await tester.pump();

    // Now the isFocusable should be gone.
    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              id: 1,
              flags: <SemanticsFlag>[
                SemanticsFlag.hasCheckedState,
                SemanticsFlag.hasEnabledState,
                SemanticsFlag.isInMutuallyExclusiveGroup,
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: const Material(child: Radio<int>(value: 2, groupValue: 2)),
      ),
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics.rootChild(
              id: 1,
              flags: <SemanticsFlag>[
                SemanticsFlag.hasCheckedState,
                SemanticsFlag.isChecked,
                SemanticsFlag.hasEnabledState,
                SemanticsFlag.isInMutuallyExclusiveGroup,
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    semantics.dispose();
  });

  testWidgets('has semantic events', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);
    final Key key = UniqueKey();
    dynamic semanticEvent;
    int? radioValue = 2;
    tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(
      SystemChannels.accessibility,
      (dynamic message) async {
        semanticEvent = message;
      },
    );

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Material(
          child: Radio<int>(
            key: key,
            value: 1,
            groupValue: radioValue,
            onChanged: (int? i) {
              radioValue = i;
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(key));
    final RenderObject object = tester.firstRenderObject(find.byKey(key));

    expect(radioValue, 1);
    expect(semanticEvent, <String, dynamic>{
      'type': 'tap',
      'nodeId': object.debugSemantics!.id,
      'data': <String, dynamic>{},
    });
    expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);

    semantics.dispose();
    tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(
      SystemChannels.accessibility,
      null,
    );
  });

  testWidgets('Material2 - Radio ink ripple is displayed correctly', (WidgetTester tester) async {
    final Key painterKey = UniqueKey();
    const radioKey = Key('radio');

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Scaffold(
          body: RepaintBoundary(
            key: painterKey,
            child: Center(
              child: Container(
                width: 100,
                height: 100,
                color: Colors.white,
                child: Radio<int>(
                  key: radioKey,
                  value: 1,
                  groupValue: 1,
                  onChanged: (int? value) {},
                ),
              ),
            ),
          ),
        ),
      ),
    );

    await tester.press(find.byKey(radioKey));
    await tester.pumpAndSettle();
    await expectLater(find.byKey(painterKey), matchesGoldenFile('m2_radio.ink_ripple.png'));
  });

  testWidgets('Material3 - Radio ink ripple is displayed correctly', (WidgetTester tester) async {
    final Key painterKey = UniqueKey();
    const radioKey = Key('radio');

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: RepaintBoundary(
            key: painterKey,
            child: Center(
              child: Container(
                width: 100,
                height: 100,
                color: Colors.white,
                child: Radio<int>(
                  key: radioKey,
                  value: 1,
                  groupValue: 1,
                  onChanged: (int? value) {},
                ),
              ),
            ),
          ),
        ),
      ),
    );

    await tester.press(find.byKey(radioKey));
    await tester.pumpAndSettle();
    await expectLater(find.byKey(painterKey), matchesGoldenFile('m3_radio.ink_ripple.png'));
  });

  testWidgets('Radio with splash radius set', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const double splashRadius = 30;
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    value: 0,
                    onChanged: (int? newValue) {},
                    focusColor: Colors.orange[500],
                    autofocus: true,
                    groupValue: 0,
                    splashRadius: splashRadius,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byWidgetPredicate((Widget widget) => widget is Radio<int>))),
      paints..circle(color: Colors.orange[500], radius: splashRadius),
    );
  });

  testWidgets('Material2 - Radio is focusable and has correct focus color', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    int? groupValue = 0;
    const radioKey = Key('radio');
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    key: radioKey,
                    value: 0,
                    onChanged: enabled
                        ? (int? newValue) {
                            setState(() {
                              groupValue = newValue;
                            });
                          }
                        : null,
                    focusColor: Colors.orange[500],
                    autofocus: true,
                    focusNode: focusNode,
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0xff2196f3))
        ..circle(color: const Color(0xff2196f3)),
    );

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0x8a000000), style: PaintingStyle.stroke, strokeWidth: 2.0),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0x61000000))
        ..circle(color: const Color(0x61000000)),
    );
    focusNode.dispose();
  });

  testWidgets('Material3 - Radio is focusable and has correct focus color', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    key: radioKey,
                    value: 0,
                    onChanged: enabled
                        ? (int? newValue) {
                            setState(() {
                              groupValue = newValue;
                            });
                          }
                        : null,
                    focusColor: Colors.orange[500],
                    autofocus: true,
                    focusNode: focusNode,
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..circle(color: theme.colorScheme.primary),
    );

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect()
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.38))
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.38)),
    );
    focusNode.dispose();
  });

  testWidgets('Material2 - Radio can be hovered and has correct hover color', (
    WidgetTester tester,
  ) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    int? groupValue = 0;
    const radioKey = Key('radio');
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    key: radioKey,
                    value: 0,
                    onChanged: enabled
                        ? (int? newValue) {
                            setState(() {
                              groupValue = newValue;
                            });
                          }
                        : null,
                    hoverColor: Colors.orange[500],
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0xff2196f3))
        ..circle(color: const Color(0xff2196f3)),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp());
    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0x8a000000), style: PaintingStyle.stroke, strokeWidth: 2.0),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0x61000000))
        ..circle(color: const Color(0x61000000)),
    );
  });

  testWidgets('Material3 - Radio can be hovered and has correct hover color', (
    WidgetTester tester,
  ) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    key: radioKey,
                    value: 0,
                    onChanged: enabled
                        ? (int? newValue) {
                            setState(() {
                              groupValue = newValue;
                            });
                          }
                        : null,
                    hoverColor: Colors.orange[500],
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..circle(color: theme.colorScheme.primary),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp());
    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.orange[500])
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface, style: PaintingStyle.stroke, strokeWidth: 2.0),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pump();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.38))
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.38)),
    );
  });

  testWidgets('Radio can be controlled by keyboard shortcuts', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    int? groupValue = 1;
    const radioKey0 = Key('radio0');
    const radioKey1 = Key('radio1');
    const radioKey2 = Key('radio2');
    final focusNode2 = FocusNode(debugLabel: 'radio2');
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 200,
                  height: 100,
                  color: Colors.white,
                  child: Row(
                    children: <Widget>[
                      Radio<int>(
                        key: radioKey0,
                        value: 0,
                        onChanged: enabled
                            ? (int? newValue) {
                                setState(() {
                                  groupValue = newValue;
                                });
                              }
                            : null,
                        hoverColor: Colors.orange[500],
                        groupValue: groupValue,
                        autofocus: true,
                      ),
                      Radio<int>(
                        key: radioKey1,
                        value: 1,
                        onChanged: enabled
                            ? (int? newValue) {
                                setState(() {
                                  groupValue = newValue;
                                });
                              }
                            : null,
                        hoverColor: Colors.orange[500],
                        groupValue: groupValue,
                      ),
                      Radio<int>(
                        key: radioKey2,
                        value: 2,
                        onChanged: enabled
                            ? (int? newValue) {
                                setState(() {
                                  groupValue = newValue;
                                });
                              }
                            : null,
                        hoverColor: Colors.orange[500],
                        groupValue: groupValue,
                        focusNode: focusNode2,
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pumpAndSettle();
    // On web, radios don't respond to the enter key.
    expect(groupValue, kIsWeb ? equals(1) : equals(0));

    focusNode2.requestFocus();
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    expect(groupValue, equals(2));

    focusNode2.dispose();
  });

  testWidgets('Radio responds to density changes.', (WidgetTester tester) async {
    const key = Key('test');
    Future<void> buildTest(VisualDensity visualDensity) async {
      return tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Material(
            child: Center(
              child: Radio<int>(
                visualDensity: visualDensity,
                key: key,
                onChanged: (int? value) {},
                value: 0,
                groupValue: 0,
              ),
            ),
          ),
        ),
      );
    }

    await buildTest(VisualDensity.standard);
    final RenderBox box = tester.renderObject(find.byKey(key));
    await tester.pumpAndSettle();
    expect(box.size, equals(const Size(48, 48)));

    await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
    await tester.pumpAndSettle();
    expect(box.size, equals(const Size(60, 60)));

    await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
    await tester.pumpAndSettle();
    expect(box.size, equals(const Size(36, 36)));

    await buildTest(const VisualDensity(horizontal: 3.0, vertical: -3.0));
    await tester.pumpAndSettle();
    expect(box.size, equals(const Size(60, 36)));
  });

  testWidgets('Radio changes mouse cursor when hovered', (WidgetTester tester) async {
    const Key key = ValueKey<int>(1);
    // Test Radio() constructor
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Align(
            alignment: Alignment.topLeft,
            child: Material(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Radio<int>(
                  key: key,
                  mouseCursor: SystemMouseCursors.text,
                  value: 1,
                  onChanged: (int? v) {},
                  groupValue: 2,
                ),
              ),
            ),
          ),
        ),
      ),
    );

    final TestGesture gesture = await tester.createGesture(
      kind: PointerDeviceKind.mouse,
      pointer: 1,
    );
    await gesture.addPointer(location: tester.getCenter(find.byKey(key)));
    addTearDown(gesture.removePointer);

    await tester.pump();

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

    // Test default cursor
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Align(
            alignment: Alignment.topLeft,
            child: Material(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Radio<int>(value: 1, onChanged: (int? v) {}, groupValue: 2),
              ),
            ),
          ),
        ),
      ),
    );
    expect(
      RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
      kIsWeb ? SystemMouseCursors.click : SystemMouseCursors.basic,
    );

    // Test default cursor when disabled
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: const Scaffold(
          body: Align(
            alignment: Alignment.topLeft,
            child: Material(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Radio<int>(value: 1, groupValue: 2),
              ),
            ),
          ),
        ),
      ),
    );

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

  testWidgets('Radio button fill color resolves in enabled/disabled states', (
    WidgetTester tester,
  ) async {
    const activeEnabledFillColor = Color(0xFF000001);
    const activeDisabledFillColor = Color(0xFF000002);
    const inactiveEnabledFillColor = Color(0xFF000003);
    const inactiveDisabledFillColor = Color(0xFF000004);

    Color getFillColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledFillColor;
        }
        return inactiveDisabledFillColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledFillColor;
      }
      return inactiveEnabledFillColor;
    }

    final WidgetStateProperty<Color> fillColor = WidgetStateColor.resolveWith(getFillColor);

    int? groupValue = 0;
    const radioKey = Key('radio');
    Widget buildApp({required bool enabled}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    key: radioKey,
                    value: 0,
                    fillColor: fillColor,
                    onChanged: enabled
                        ? (int? newValue) {
                            setState(() {
                              groupValue = newValue;
                            });
                          }
                        : null,
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(enabled: true));

    // Selected and enabled.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: activeEnabledFillColor)
        ..circle(color: activeEnabledFillColor),
    );

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: true));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: inactiveEnabledFillColor, style: PaintingStyle.stroke, strokeWidth: 2.0),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: activeDisabledFillColor)
        ..circle(color: activeDisabledFillColor),
    );

    // Check when the radio is unselected and disabled.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: inactiveDisabledFillColor, style: PaintingStyle.stroke, strokeWidth: 2.0),
    );
  });

  testWidgets('Material2 - Radio fill color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredFillColor = Color(0xFF000001);
    const focusedFillColor = Color(0xFF000002);

    Color getFillColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredFillColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedFillColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> fillColor = WidgetStateColor.resolveWith(getFillColor);

    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData(useMaterial3: false);
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    autofocus: true,
                    focusNode: focusNode,
                    key: radioKey,
                    value: 0,
                    fillColor: fillColor,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.black12)
        ..circle(color: Colors.transparent)
        ..circle(color: focusedFillColor),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: theme.hoverColor)
        ..circle(color: Colors.transparent)
        ..circle(color: hoveredFillColor),
    );

    focusNode.dispose();
  });

  testWidgets('Material3 - Radio fill color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredFillColor = Color(0xFF000001);
    const focusedFillColor = Color(0xFF000002);

    Color getFillColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredFillColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedFillColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> fillColor = WidgetStateColor.resolveWith(getFillColor);

    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: Radio<int>(
                    autofocus: true,
                    focusNode: focusNode,
                    key: radioKey,
                    value: 0,
                    fillColor: fillColor,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    groupValue: groupValue,
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect()
        ..circle(color: theme.colorScheme.primary.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: focusedFillColor),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: theme.colorScheme.primary.withOpacity(0.08))
        ..circle(color: Colors.transparent)
        ..circle(color: hoveredFillColor),
    );

    focusNode.dispose();
  });

  testWidgets('Radio overlay color resolves in active/pressed/focused/hovered states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;

    const fillColor = Color(0xFF000000);
    const activePressedOverlayColor = Color(0xFF000001);
    const inactivePressedOverlayColor = Color(0xFF000002);
    const hoverOverlayColor = Color(0xFF000003);
    const focusOverlayColor = Color(0xFF000004);
    const hoverColor = Color(0xFF000005);
    const focusColor = Color(0xFF000006);

    Color? getOverlayColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.pressed)) {
        if (states.contains(WidgetState.selected)) {
          return activePressedOverlayColor;
        }
        return inactivePressedOverlayColor;
      }
      if (states.contains(WidgetState.hovered)) {
        return hoverOverlayColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusOverlayColor;
      }
      return null;
    }

    const splashRadius = 24.0;

    Finder findRadio() {
      return find.byWidgetPredicate((Widget widget) => widget is Radio<bool>);
    }

    MaterialInkController? getRadioMaterial(WidgetTester tester) {
      return Material.of(tester.element(findRadio()));
    }

    Widget buildRadio({bool active = false, bool focused = false, bool useOverlay = true}) {
      return MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(
            focusNode: focusNode,
            autofocus: focused,
            value: active,
            groupValue: true,
            onChanged: (_) {},
            fillColor: const MaterialStatePropertyAll<Color>(fillColor),
            overlayColor: useOverlay ? WidgetStateProperty.resolveWith(getOverlayColor) : null,
            hoverColor: hoverColor,
            focusColor: focusColor,
            splashRadius: splashRadius,
          ),
        ),
      );
    }

    await tester.pumpWidget(buildRadio(useOverlay: false));
    await tester.press(findRadio());
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints..circle(color: fillColor.withAlpha(kRadialReactionAlpha), radius: splashRadius),
      reason: 'Default inactive pressed Radio should have overlay color from fillColor',
    );

    await tester.pumpWidget(buildRadio(active: true, useOverlay: false));
    await tester.press(findRadio());
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints..circle(color: fillColor.withAlpha(kRadialReactionAlpha), radius: splashRadius),
      reason: 'Default active pressed Radio should have overlay color from fillColor',
    );

    await tester.pumpWidget(buildRadio());
    await tester.press(findRadio());
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints..circle(color: inactivePressedOverlayColor, radius: splashRadius),
      reason: 'Inactive pressed Radio should have overlay color: $inactivePressedOverlayColor',
    );

    await tester.pumpWidget(buildRadio(active: true));
    await tester.press(findRadio());
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints..circle(color: activePressedOverlayColor, radius: splashRadius),
      reason: 'Active pressed Radio should have overlay color: $activePressedOverlayColor',
    );

    await tester.pumpWidget(Container());
    await tester.pumpWidget(buildRadio(focused: true));
    await tester.pumpAndSettle();

    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      getRadioMaterial(tester),
      paints..circle(color: focusOverlayColor, radius: splashRadius),
      reason: 'Focused Radio should use overlay color $focusOverlayColor over $focusColor',
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(findRadio()));
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints..circle(color: hoverOverlayColor, radius: splashRadius),
      reason: 'Hovered Radio should use overlay color $hoverOverlayColor over $hoverColor',
    );

    focusNode.dispose();
  });

  testWidgets('Do not crash when widget disappears while pointer is down', (
    WidgetTester tester,
  ) async {
    final Key key = UniqueKey();

    Widget buildRadio(bool show) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: show
                ? Radio<bool>(key: key, value: true, groupValue: false, onChanged: (_) {})
                : Container(),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildRadio(true));
    final Offset center = tester.getCenter(find.byKey(key));
    // Put a pointer down on the screen.
    final TestGesture gesture = await tester.startGesture(center);
    await tester.pump();
    // While the pointer is down, the widget disappears.
    await tester.pumpWidget(buildRadio(false));
    expect(find.byKey(key), findsNothing);
    // Release pointer after widget disappeared.
    await gesture.up();
  });

  testWidgets('disabled radio shows tooltip', (WidgetTester tester) async {
    const longPressTooltip = 'long press tooltip';
    const tapTooltip = 'tap tooltip';
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: const Material(
          child: Tooltip(
            message: longPressTooltip,
            child: Radio<bool>(value: true, groupValue: false),
          ),
        ),
      ),
    );

    // Default tooltip shows up after long pressed.
    final Finder tooltip0 = find.byType(Tooltip);
    expect(find.text(longPressTooltip), findsNothing);

    await tester.tap(tooltip0);
    await tester.pump(const Duration(milliseconds: 10));
    expect(find.text(longPressTooltip), findsNothing);

    final TestGesture gestureLongPress = await tester.startGesture(tester.getCenter(tooltip0));
    await tester.pump();
    await tester.pump(kLongPressTimeout);
    await gestureLongPress.up();
    await tester.pump();

    expect(find.text(longPressTooltip), findsOneWidget);

    // Tooltip shows up after tapping when set triggerMode to TooltipTriggerMode.tap.
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: const Material(
          child: Tooltip(
            triggerMode: TooltipTriggerMode.tap,
            message: tapTooltip,
            child: Radio<bool>(value: true, groupValue: false),
          ),
        ),
      ),
    );

    await tester.pump(const Duration(days: 1));
    await tester.pumpAndSettle();
    expect(find.text(tapTooltip), findsNothing);
    expect(find.text(longPressTooltip), findsNothing);

    final Finder tooltip1 = find.byType(Tooltip);
    await tester.tap(tooltip1);
    await tester.pump(const Duration(milliseconds: 10));
    expect(find.text(tapTooltip), findsOneWidget);
  });

  testWidgets('Material2 - Radio button default colors', (WidgetTester tester) async {
    Widget buildRadio({bool enabled = true, bool selected = true}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Scaffold(
          body: Radio<bool>(value: true, groupValue: true, onChanged: enabled ? (_) {} : null),
        ),
      );
    }

    await tester.pumpWidget(buildRadio());
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0xFF2196F3)) // Outer circle - primary value
        ..circle(color: const Color(0xFF2196F3))
        ..restore(), // Inner circle - primary value
    );

    await tester.pumpWidget(Container());
    await tester.pumpWidget(buildRadio(selected: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..save()
        ..circle(color: Colors.transparent)
        ..circle(color: const Color(0xFF2196F3))
        ..restore(),
    );

    await tester.pumpWidget(Container());
    await tester.pumpWidget(buildRadio(enabled: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: Colors.black38),
    );
  });

  testWidgets('Material3 - Radio button default colors', (WidgetTester tester) async {
    final theme = ThemeData();
    Widget buildRadio({bool enabled = true, bool selected = true}) {
      return MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(value: true, groupValue: true, onChanged: enabled ? (_) {} : null),
        ),
      );
    }

    await tester.pumpWidget(buildRadio());
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary) // Outer circle - primary value
        ..circle(color: theme.colorScheme.primary)
        ..restore(), // Inner circle - primary value
    );

    await tester.pumpWidget(Container());
    await tester.pumpWidget(buildRadio(selected: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..save()
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..restore(),
    );

    await tester.pumpWidget(Container());
    await tester.pumpWidget(buildRadio(enabled: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.38)),
    );
  });

  testWidgets('Material2 - Radio button default overlay colors in hover/focus/press states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;

    final theme = ThemeData(useMaterial3: false);
    final ColorScheme colors = theme.colorScheme;
    Widget buildRadio({bool enabled = true, bool focused = false, bool selected = true}) {
      return MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(
            focusNode: focusNode,
            autofocus: focused,
            value: true,
            groupValue: selected,
            onChanged: enabled ? (_) {} : null,
          ),
        ),
      );
    }

    // default selected radio
    await tester.pumpWidget(buildRadio());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: colors.secondary),
    );

    // selected radio in pressed state
    await tester.pumpWidget(buildRadio());
    final TestGesture gesture1 = await tester.startGesture(
      tester.getCenter(find.byType(Radio<bool>)),
    );
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.secondary.withAlpha(0x1F))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.secondary),
    );

    // unselected radio in pressed state
    await tester.pumpWidget(buildRadio(selected: false));
    final TestGesture gesture2 = await tester.startGesture(
      tester.getCenter(find.byType(Radio<bool>)),
    );
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: theme.unselectedWidgetColor.withAlpha(0x1F))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.unselectedWidgetColor),
    );

    // selected radio in focused state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio(focused: true));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: theme.focusColor)
        ..circle(color: Colors.transparent)
        ..circle(color: colors.secondary),
    );

    // unselected radio in focused state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio(focused: true, selected: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: theme.focusColor)
        ..circle(color: Colors.transparent)
        ..circle(color: theme.unselectedWidgetColor),
    );

    // selected radio in hovered state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio());
    final TestGesture gesture3 = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture3.addPointer();
    await gesture3.moveTo(tester.getCenter(find.byType(Radio<bool>)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: theme.hoverColor)
        ..circle(color: Colors.transparent)
        ..circle(color: colors.secondary),
    );

    focusNode.dispose();

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

  testWidgets('Material3 - Radio button default overlay colors in hover/focus/press states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;

    final theme = ThemeData();
    final ColorScheme colors = theme.colorScheme;
    Widget buildRadio({bool enabled = true, bool focused = false, bool selected = true}) {
      return MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(
            focusNode: focusNode,
            autofocus: focused,
            value: true,
            groupValue: selected,
            onChanged: enabled ? (_) {} : null,
          ),
        ),
      );
    }

    // default selected radio
    await tester.pumpWidget(buildRadio());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: Colors.transparent)
        ..circle(color: colors.primary.withOpacity(1)),
    );

    // selected radio in pressed state
    await tester.pumpWidget(buildRadio());
    final TestGesture gesture1 = await tester.startGesture(
      tester.getCenter(find.byType(Radio<bool>)),
    );
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.onSurface.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.primary.withOpacity(1)),
    );

    // unselected radio in pressed state
    await tester.pumpWidget(buildRadio(selected: false));
    final TestGesture gesture2 = await tester.startGesture(
      tester.getCenter(find.byType(Radio<bool>)),
    );
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.primary.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.onSurfaceVariant.withOpacity(1)),
    );

    // selected radio in focused state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio(focused: true));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.primary.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.primary.withOpacity(1)),
    );

    // unselected radio in focused state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio(focused: true, selected: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.onSurface.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.onSurface.withOpacity(1)),
    );

    // selected radio in hovered state
    await tester.pumpWidget(Container()); // reset test
    await tester.pumpWidget(buildRadio());
    final TestGesture gesture3 = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture3.addPointer();
    await gesture3.moveTo(tester.getCenter(find.byType(Radio<bool>)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Radio<bool>))),
      paints
        ..circle(color: colors.primary.withOpacity(0.08))
        ..circle(color: Colors.transparent)
        ..circle(color: colors.primary.withOpacity(1)),
    );

    focusNode.dispose();

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

  testWidgets('Radio.adaptive shows the correct platform widget', (WidgetTester tester) async {
    Widget buildApp(TargetPlatform platform) {
      return MaterialApp(
        theme: ThemeData(platform: platform),
        home: Material(
          child: Center(child: Radio<int>.adaptive(value: 1, groupValue: 2, onChanged: (_) {})),
        ),
      );
    }

    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      await tester.pumpWidget(buildApp(platform));
      await tester.pumpAndSettle();

      expect(find.byType(CupertinoRadio<int>), findsOneWidget);
    }

    for (final platform in <TargetPlatform>[
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.linux,
      TargetPlatform.windows,
    ]) {
      await tester.pumpWidget(buildApp(platform));
      await tester.pumpAndSettle();

      expect(find.byType(CupertinoRadio<int>), findsNothing);
    }
  });

  testWidgets('Material2 - Radio default overlayColor and fillColor resolves pressed state', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    final theme = ThemeData(useMaterial3: false);

    Finder findRadio() {
      return find.byWidgetPredicate((Widget widget) => widget is Radio<bool>);
    }

    MaterialInkController? getRadioMaterial(WidgetTester tester) {
      return Material.of(tester.element(findRadio()));
    }

    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(focusNode: focusNode, value: true, groupValue: true, onChanged: (_) {}),
        ),
      ),
    );

    // Hover
    final Offset center = tester.getCenter(find.byType(Radio<bool>));
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(center);
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.hoverColor)
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.secondary),
    );

    // Highlighted (pressed).
    await gesture.down(center);
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.colorScheme.secondary.withAlpha(kRadialReactionAlpha))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.secondary),
    );
    // Remove pressed and hovered states
    await gesture.up();
    await tester.pumpAndSettle();
    await gesture.moveTo(const Offset(0, 50));
    await tester.pumpAndSettle();

    // Focused.
    focusNode.requestFocus();
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.focusColor)
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.secondary),
    );
    focusNode.dispose();
  });

  testWidgets('Material3 - Radio default overlayColor and fillColor resolves pressed state', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    final theme = ThemeData();

    Finder findRadio() {
      return find.byWidgetPredicate((Widget widget) => widget is Radio<bool>);
    }

    MaterialInkController? getRadioMaterial(WidgetTester tester) {
      return Material.of(tester.element(findRadio()));
    }

    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Radio<bool>(focusNode: focusNode, value: true, groupValue: true, onChanged: (_) {}),
        ),
      ),
    );

    // Hover
    final Offset center = tester.getCenter(find.byType(Radio<bool>));
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(center);
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.colorScheme.primary.withOpacity(0.08))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary),
    );

    // Highlighted (pressed).
    await gesture.down(center);
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.colorScheme.onSurface.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary),
    );
    // Remove pressed and hovered states
    await gesture.up();
    await tester.pumpAndSettle();
    await gesture.moveTo(const Offset(0, 50));
    await tester.pumpAndSettle();

    // Focused.
    focusNode.requestFocus();
    await tester.pumpAndSettle();

    expect(
      getRadioMaterial(tester),
      paints
        ..circle(color: theme.colorScheme.primary.withOpacity(0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary),
    );
    focusNode.dispose();
  });

  testWidgets('Radio button background color resolves in enabled/disabled states', (
    WidgetTester tester,
  ) async {
    const activeEnabledBackgroundColor = Color(0xFF000001);
    const activeDisabledBackgroundColor = Color(0xFF000002);
    const inactiveEnabledBackgroundColor = Color(0xFF000003);
    const inactiveDisabledBackgroundColor = Color(0xFF000004);

    Color getBackgroundColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledBackgroundColor;
        }
        return inactiveDisabledBackgroundColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledBackgroundColor;
      }
      return inactiveEnabledBackgroundColor;
    }

    final WidgetStateProperty<Color> backgroundColor = WidgetStateColor.resolveWith(
      getBackgroundColor,
    );

    int? groupValue = 0;
    const radioKey = Key('radio');
    Widget buildApp({required bool enabled}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: groupValue,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    child: Radio<int>(
                      key: radioKey,
                      value: 0,
                      backgroundColor: backgroundColor,
                      enabled: enabled,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(enabled: true));

    // Selected and enabled.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: activeEnabledBackgroundColor),
    );

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: true));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: inactiveEnabledBackgroundColor),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: activeDisabledBackgroundColor),
    );

    // Check when the radio is unselected and disabled.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: inactiveDisabledBackgroundColor),
    );
  });

  testWidgets('Radio background color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredBackgroundColor = Color(0xFF000001);
    const focusedBackgroundColor = Color(0xFF000002);

    Color getBackgroundColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredBackgroundColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedBackgroundColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> backgroundColor = WidgetStateColor.resolveWith(
      getBackgroundColor,
    );

    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: groupValue,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    child: Radio<int>(
                      autofocus: true,
                      focusNode: focusNode,
                      key: radioKey,
                      value: 0,
                      backgroundColor: backgroundColor,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect()
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.1))
        ..circle(color: focusedBackgroundColor),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.08))
        ..circle(color: hoveredBackgroundColor),
    );

    focusNode.dispose();
  });

  testWidgets('Radio button side resolves in enabled/disabled states', (WidgetTester tester) async {
    const activeEnabledSide = BorderSide(color: Color(0xFF000001));
    const activeDisabledSide = BorderSide(color: Color(0xFF000002), width: 2);
    const inactiveEnabledSide = BorderSide(color: Color(0xFF000003), width: 3);
    const inactiveDisabledSide = BorderSide(color: Color(0xFF000004), width: 4);

    BorderSide getSide(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledSide;
        }
        return inactiveDisabledSide;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledSide;
      }
      return inactiveEnabledSide;
    }

    final side = WidgetStateBorderSide.resolveWith(getSide);

    int? groupValue = 0;
    const radioKey = Key('radio');
    Widget buildApp({required bool enabled}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: groupValue,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    child: Radio<int>(key: radioKey, value: 0, side: side, enabled: enabled),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(enabled: true));

    // Selected and enabled.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: activeEnabledSide.color, strokeWidth: activeEnabledSide.width),
    );

    // Check when the radio isn't selected.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: true));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: inactiveEnabledSide.color, strokeWidth: inactiveEnabledSide.width),
    );

    // Check when the radio is selected, but disabled.
    groupValue = 0;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: activeDisabledSide.color, strokeWidth: activeDisabledSide.width),
    );

    // Check when the radio is unselected and disabled.
    groupValue = 1;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: inactiveDisabledSide.color, strokeWidth: inactiveDisabledSide.width),
    );
  });

  testWidgets('Radio background color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredSide = BorderSide(color: Color(0xFF000001));
    const focusedSide = BorderSide(color: Color(0xFF000002), width: 2);

    BorderSide? getSide(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredSide;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedSide;
      }
      return null;
    }

    final side = WidgetStateBorderSide.resolveWith(getSide);

    int? groupValue = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: groupValue,
                    onChanged: (int? newValue) {
                      setState(() {
                        groupValue = newValue;
                      });
                    },
                    child: Radio<int>(
                      autofocus: true,
                      focusNode: focusNode,
                      key: radioKey,
                      value: 0,
                      side: side,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect()
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: focusedSide.color, strokeWidth: focusedSide.width),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.08))
        ..circle(color: Colors.transparent)
        ..circle(color: hoveredSide.color, strokeWidth: hoveredSide.width),
    );

    focusNode.dispose();
  });

  testWidgets('Radio button inner radius resolves in enabled/disabled states', (
    WidgetTester tester,
  ) async {
    const double enabledInnerRadius = 1;
    const double disabledInnerRadius = 2;

    double getInnerRadius(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        return disabledInnerRadius;
      }
      return enabledInnerRadius;
    }

    final WidgetStateProperty<double> innerRadius = WidgetStateProperty.resolveWith(getInnerRadius);

    const value = 0;
    const radioKey = Key('radio');
    Widget buildApp({required bool enabled}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: value,
                    onChanged: (int? newValue) {},
                    child: Radio<int>(
                      key: radioKey,
                      value: value,
                      innerRadius: innerRadius,
                      enabled: enabled,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(enabled: true));

    // Enabled.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..circle(radius: enabledInnerRadius, color: theme.colorScheme.primary),
    );

    // Disabled.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.onSurface.withAlpha(97))
        ..circle(radius: disabledInnerRadius, color: theme.colorScheme.onSurface.withAlpha(97)),
    );
  });

  testWidgets('Radio inner radius resolves in hovered/focused states', (WidgetTester tester) async {
    final focusNode = FocusNode(debugLabel: 'radio');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const double hoveredInnerRadius = 1;
    const double focusedInnerRadius = 2;
    double? getInnerRadius(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredInnerRadius;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedInnerRadius;
      }
      return null;
    }

    final WidgetStateProperty<double?> innerRadius = WidgetStateProperty.resolveWith(
      getInnerRadius,
    );

    const value = 0;
    const radioKey = Key('radio');
    final theme = ThemeData();
    Widget buildApp() {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Container(
                  width: 100,
                  height: 100,
                  color: Colors.white,
                  child: RadioGroup<int>(
                    groupValue: value,
                    onChanged: (int? newValue) {},
                    child: Radio<int>(
                      autofocus: true,
                      focusNode: focusNode,
                      key: radioKey,
                      value: value,
                      innerRadius: innerRadius,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect()
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.1))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..circle(radius: focusedInnerRadius, color: theme.colorScheme.primary),
    );

    // Start hovering
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(tester.getCenter(find.byKey(radioKey)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byKey(radioKey))),
      paints
        ..rect(
          color: const Color(0xffffffff),
          rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
        )
        ..circle(color: theme.colorScheme.primary.withValues(alpha: 0.08))
        ..circle(color: Colors.transparent)
        ..circle(color: theme.colorScheme.primary)
        ..circle(radius: hoveredInnerRadius, color: theme.colorScheme.primary),
    );

    focusNode.dispose();
  });

  // Regression tests for https://github.com/flutter/flutter/issues/170422
  group('Radio accessibility announcements on various platforms', () {
    testWidgets('Unselected radio should be vocalized via hint on iOS/macOS platform', (
      WidgetTester tester,
    ) async {
      const WidgetsLocalizations localizations = DefaultWidgetsLocalizations();
      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Material(
            child: RadioGroup<int>(
              groupValue: 2,
              onChanged: (int? value) {},
              child: const Radio<int>(value: 1),
            ),
          ),
        ),
      );
      final SemanticsNode semanticNode = tester.getSemantics(find.byType(Focus).last);
      if (defaultTargetPlatform == TargetPlatform.iOS ||
          defaultTargetPlatform == TargetPlatform.macOS) {
        expect(semanticNode.hint, localizations.radioButtonUnselectedLabel);
      } else {
        expect(semanticNode.hint, anyOf(isNull, isEmpty));
      }
    });

    testWidgets('Selected radio should be vocalized via the selected flag on all platforms', (
      WidgetTester tester,
    ) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Material(
            child: RadioGroup<int>(
              groupValue: 1,
              onChanged: (int? value) {},
              child: const Radio<int>(value: 1),
            ),
          ),
        ),
      );

      final SemanticsNode semanticNode = tester.getSemantics(find.byType(Focus).last);
      // Radio semantics should not have hint.
      expect(semanticNode.hint, anyOf(isNull, isEmpty));
    });
  });

  testWidgets('Radio does not crash at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(
          body: Center(child: SizedBox.shrink(child: Radio<bool>(value: true))),
        ),
      ),
    );
    expect(tester.getSize(find.byType(Radio<bool>)), Size.zero);
  });
}
