// 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:async';
import 'dart:ui' as ui;

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

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

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

  testWidgets('Switch can toggle on tap', (WidgetTester tester) async {
    final Key switchKey = UniqueKey();
    var value = false;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return MaterialApp(
              theme: theme,
              home: Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    key: switchKey,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );

    expect(value, isFalse);
    await tester.tap(find.byKey(switchKey));
    expect(value, isTrue);
  });

  testWidgets('Switch size is configurable by ThemeData.materialTapTargetSize', (
    WidgetTester tester,
  ) async {
    final bool material3 = theme.useMaterial3;
    await tester.pumpWidget(
      Theme(
        data: theme.copyWith(materialTapTargetSize: MaterialTapTargetSize.padded),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: Switch(
                dragStartBehavior: DragStartBehavior.down,
                value: true,
                onChanged: (bool newValue) {},
              ),
            ),
          ),
        ),
      ),
    );

    // switch width = trackWidth - 2 * trackRadius + _kSwitchMinSize
    // M2 width = 33 - 2 * 7 + 40
    // M3 width = 52 - 2 * 16 + 40
    expect(
      tester.getSize(find.byType(Switch)),
      material3 ? const Size(60.0, 48.0) : const Size(59.0, 48.0),
    );

    await tester.pumpWidget(
      Theme(
        data: theme.copyWith(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: Switch(
                dragStartBehavior: DragStartBehavior.down,
                value: true,
                onChanged: (bool newValue) {},
              ),
            ),
          ),
        ),
      ),
    );

    expect(
      tester.getSize(find.byType(Switch)),
      material3 ? const Size(60.0, 40.0) : const Size(59.0, 40.0),
    );
  });

  testWidgets('Material2 - Switch does not get distorted upon changing constraints with parent', (
    WidgetTester tester,
  ) async {
    const double maxWidth = 300;
    const double maxHeight = 100;

    const boundaryKey = ValueKey<String>('switch container');

    Widget buildSwitch({required double width, required double height}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Scaffold(
          body: Directionality(
            textDirection: TextDirection.ltr,
            child: SizedBox(
              width: maxWidth,
              height: maxHeight,
              child: RepaintBoundary(
                key: boundaryKey,
                child: SizedBox(
                  width: width,
                  height: height,
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                  ),
                ),
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(width: maxWidth, height: maxHeight));
    await expectLater(find.byKey(boundaryKey), matchesGoldenFile('m2_switch_test.big.on.png'));

    await tester.pumpWidget(buildSwitch(width: 20, height: 10));
    await expectLater(find.byKey(boundaryKey), matchesGoldenFile('m2_switch_test.small.on.png'));
  });

  testWidgets('Material3 - Switch does not get distorted upon changing constraints with parent', (
    WidgetTester tester,
  ) async {
    const double maxWidth = 300;
    const double maxHeight = 100;

    const boundaryKey = ValueKey<String>('switch container');

    Widget buildSwitch({required double width, required double height}) {
      return MaterialApp(
        home: Scaffold(
          body: Directionality(
            textDirection: TextDirection.ltr,
            child: SizedBox(
              width: maxWidth,
              height: maxHeight,
              child: RepaintBoundary(
                key: boundaryKey,
                child: SizedBox(
                  width: width,
                  height: height,
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                  ),
                ),
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(width: maxWidth, height: maxHeight));
    await expectLater(find.byKey(boundaryKey), matchesGoldenFile('m3_switch_test.big.on.png'));

    await tester.pumpWidget(buildSwitch(width: 20, height: 10));
    await expectLater(find.byKey(boundaryKey), matchesGoldenFile('m3_switch_test.small.on.png'));
  });

  testWidgets('Switch can drag (LTR)', (WidgetTester tester) async {
    var value = false;

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, isFalse);

    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));

    expect(value, isFalse);

    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));

    expect(value, isTrue);

    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));

    expect(value, isTrue);

    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));

    expect(value, isFalse);
  });

  testWidgets('Switch can drag with dragStartBehavior', (WidgetTester tester) async {
    var value = false;

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, isFalse);
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    expect(value, isFalse);

    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));
    expect(value, isTrue);
    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));
    expect(value, isTrue);
    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    expect(value, isFalse);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return Material(
              child: Center(
                child: Switch(
                  value: value,
                  onChanged: (bool newValue) {
                    setState(() {
                      value = newValue;
                    });
                  },
                ),
              ),
            );
          },
        ),
      ),
    );
    await tester.pumpAndSettle();
    final Rect switchRect = tester.getRect(find.byType(Switch));

    TestGesture gesture = await tester.startGesture(switchRect.center);
    // We have to execute the drag in two frames because the first update will
    // just set the start position.
    await gesture.moveBy(const Offset(20.0, 0.0));
    await gesture.moveBy(const Offset(20.0, 0.0));
    expect(value, isFalse);
    await gesture.up();
    expect(value, isTrue);
    await tester.pump();

    gesture = await tester.startGesture(switchRect.center);
    await gesture.moveBy(const Offset(20.0, 0.0));
    await gesture.moveBy(const Offset(20.0, 0.0));
    expect(value, isTrue);
    await gesture.up();
    expect(value, isTrue);
    await tester.pump();

    gesture = await tester.startGesture(switchRect.center);
    await gesture.moveBy(const Offset(-20.0, 0.0));
    await gesture.moveBy(const Offset(-20.0, 0.0));
    expect(value, isTrue);
    await gesture.up();
    expect(value, isFalse);
  });

  testWidgets('Switch can drag (RTL)', (WidgetTester tester) async {
    var value = false;

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));

    expect(value, isFalse);

    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));

    expect(value, isTrue);

    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));

    expect(value, isTrue);

    await tester.pump();
    await tester.drag(find.byType(Switch), const Offset(30.0, 0.0));

    expect(value, isFalse);
  });

  testWidgets('Material2 - Switch has default colors when enabled', (WidgetTester tester) async {
    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x52000000), // Black with 32% opacity
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: Colors.grey.shade50),
      reason: 'Inactive enabled switch should match these colors',
    );
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    await tester.pump();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xff2196f3)),
      reason: 'Active enabled switch should match these colors',
    );
  });

  testWidgets('Material3 - Switch has default colors when enabled', (WidgetTester tester) async {
    final theme = ThemeData();
    final ColorScheme colors = theme.colorScheme;
    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.outline,
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..rrect(color: colors.outline), // thumb color
      reason: 'Inactive enabled switch should match these colors',
    );
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    await tester.pump();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: colors.onPrimary), // thumb color
      reason: 'Active enabled switch should match these colors',
    );
  });

  testWidgets('Switch.adaptive(Cupertino) has default colors when enabled', (
    WidgetTester tester,
  ) async {
    final theme = ThemeData();
    final ColorScheme colors = theme.colorScheme;
    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch.adaptive(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.outline,
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..rrect(color: colors.outline), // thumb color
      reason: 'Inactive enabled switch should match these colors',
    );
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    await tester.pump();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: colors.onPrimary), // thumb color
      reason: 'Active enabled switch should match these colors',
    );
  });

  testWidgets('Material2 - Switch has default colors when disabled', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: const Directionality(
          textDirection: TextDirection.rtl,
          child: Material(child: Center(child: Switch(value: false, onChanged: null))),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: Colors.grey.shade400),
      reason: 'Inactive disabled switch should match these colors',
    );

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: const Directionality(
          textDirection: TextDirection.rtl,
          child: Material(child: Center(child: Switch(value: true, onChanged: null))),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: Colors.grey.shade400),
      reason: 'Active disabled switch should match these colors',
    );
  });

  testWidgets('Material3 - Inactive Switch has default colors when disabled', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;

    await tester.pumpWidget(
      MaterialApp(
        theme: themeData,
        home: const Directionality(
          textDirection: TextDirection.rtl,
          child: Material(child: Center(child: Switch(value: false, onChanged: null))),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..rrect(
          color: Color.alphaBlend(colors.onSurface.withOpacity(0.38), colors.surface),
        ), // thumb color
      reason: 'Inactive disabled switch should match these colors',
    );
  });

  testWidgets('Material3 - Active Switch has default colors when disabled', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;
    await tester.pumpWidget(
      MaterialApp(
        theme: themeData,
        home: const Directionality(
          textDirection: TextDirection.rtl,
          child: Material(child: Center(child: Switch(value: true, onChanged: null))),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..save()
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: colors.surface), // thumb color
      reason: 'Active disabled switch should match these colors',
    );
  });

  testWidgets('Material2 - Switch default overlayColor resolves hovered/focused state', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    Finder findSwitch() {
      return find.byWidgetPredicate((Widget widget) => widget is Switch);
    }

    MaterialInkController? getSwitchMaterial(WidgetTester tester) {
      return Material.of(tester.element(findSwitch()));
    }

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Scaffold(
          body: Switch(focusNode: focusNode, value: true, onChanged: (_) {}),
        ),
      ),
    );

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

    expect(getSwitchMaterial(tester), paints..circle(color: theme.focusColor));

    // On both hovered and focused, the overlay color should show hovered overlay color.
    final Offset center = tester.getCenter(find.byType(Switch));
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(center);
    await tester.pumpAndSettle();

    expect(getSwitchMaterial(tester), paints..circle(color: theme.hoverColor));

    focusNode.dispose();
  });

  testWidgets('Material3 - Switch default overlayColor resolves hovered/focused state', (
    WidgetTester tester,
  ) async {
    final theme = ThemeData();
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;

    Finder findSwitch() {
      return find.byWidgetPredicate((Widget widget) => widget is Switch);
    }

    MaterialInkController? getSwitchMaterial(WidgetTester tester) {
      return Material.of(tester.element(findSwitch()));
    }

    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Switch(focusNode: focusNode, value: true, onChanged: (_) {}),
        ),
      ),
    );

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

    expect(
      getSwitchMaterial(tester),
      paints..circle(color: theme.colorScheme.primary.withOpacity(0.1)),
    );

    // On both hovered and focused, the overlay color should show hovered overlay color.
    final Offset center = tester.getCenter(find.byType(Switch));
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    addTearDown(gesture.removePointer);
    await gesture.moveTo(center);
    await tester.pumpAndSettle();

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

    focusNode.dispose();
  });

  testWidgets('Material2 - Switch can be set color', (WidgetTester tester) async {
    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                    activeColor: Colors.red[500],
                    activeTrackColor: Colors.green[500],
                    inactiveThumbColor: Colors.yellow[500],
                    inactiveTrackColor: Colors.blue[500],
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.blue[500],
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: Colors.yellow[500]),
    );
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    await tester.pump();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.green[500],
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: Colors.red[500]),
    );
  });

  testWidgets('Material3 - Switch can be set color', (WidgetTester tester) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;

    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: themeData,
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                    activeColor: Colors.red[500],
                    activeTrackColor: Colors.green[500],
                    inactiveThumbColor: Colors.yellow[500],
                    inactiveTrackColor: Colors.blue[500],
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: Colors.blue[500],
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(style: PaintingStyle.stroke, color: colors.outline)
        ..rrect(color: Colors.yellow[500]), // thumb color
    );
    await tester.drag(find.byType(Switch), const Offset(-30.0, 0.0));
    await tester.pump();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: Colors.green[500],
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: Colors.red[500]), // thumb color
    );
  });

  testWidgets('Drag ends after animation completes', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/17773

    var value = false;
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, isFalse);

    final Rect switchRect = tester.getRect(find.byType(Switch));
    final TestGesture gesture = await tester.startGesture(switchRect.centerLeft);
    await tester.pump();
    await gesture.moveBy(Offset(switchRect.width, 0.0));
    await tester.pump();
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200));

    expect(value, isTrue);
    expect(tester.hasRunningAnimations, false);
  });

  testWidgets('can veto switch dragging result', (WidgetTester tester) async {
    var value = false;

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = value || newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Move a little to the right, not past the middle.
    TestGesture gesture = await tester.startGesture(tester.getRect(find.byType(Switch)).center);
    await gesture.moveBy(const Offset(kTouchSlop + 0.1, 0.0));
    await tester.pump();
    await gesture.moveBy(const Offset(-kTouchSlop + 5.1, 0.0));
    await tester.pump();
    await gesture.up();
    await tester.pump();
    expect(value, isFalse);
    final ToggleableStateMixin state = tester.state<ToggleableStateMixin>(
      find.descendant(
        of: find.byType(Switch),
        matching: find.byWidgetPredicate(
          (Widget widget) => widget.runtimeType.toString() == '_MaterialSwitch',
        ),
      ),
    );
    expect(state.position.value, lessThan(0.5));
    await tester.pump();
    await tester.pumpAndSettle();
    expect(value, isFalse);
    expect(state.position.value, 0);

    // Move past the middle.
    gesture = await tester.startGesture(tester.getRect(find.byType(Switch)).center);
    await gesture.moveBy(const Offset(kTouchSlop + 0.1, 0.0));
    await tester.pump();
    await gesture.up();
    await tester.pump();
    expect(value, isTrue);
    expect(state.position.value, greaterThan(0.5));

    await tester.pump();
    await tester.pumpAndSettle();
    expect(value, isTrue);
    expect(state.position.value, 1.0);

    // Now move back to the left, the revert animation should play.
    gesture = await tester.startGesture(tester.getRect(find.byType(Switch)).center);
    await gesture.moveBy(const Offset(-kTouchSlop - 0.1, 0.0));
    await tester.pump();
    await gesture.up();
    await tester.pump();
    expect(value, isTrue);
    expect(state.position.value, lessThan(0.5));

    await tester.pump();
    await tester.pumpAndSettle();
    expect(value, isTrue);
    expect(state.position.value, 1.0);
  });

  testWidgets('switch has semantic events', (WidgetTester tester) async {
    dynamic semanticEvent;
    var value = false;
    tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(
      SystemChannels.accessibility,
      (dynamic message) async {
        semanticEvent = message;
      },
    );
    final semanticsTester = SemanticsTester(tester);

    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    value: value,
                    onChanged: (bool newValue) {
                      setState(() {
                        value = newValue;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
    await tester.tap(find.byType(Switch));
    final RenderObject object = tester.firstRenderObject(find.byType(Switch));

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

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

  testWidgets('switch sends semantic events from parent if fully merged', (
    WidgetTester tester,
  ) async {
    dynamic semanticEvent;
    var value = false;
    tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(
      SystemChannels.accessibility,
      (dynamic message) async {
        semanticEvent = message;
      },
    );
    final semanticsTester = SemanticsTester(tester);

    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            void onChanged(bool newValue) {
              setState(() {
                value = newValue;
              });
            }

            return Material(
              child: MergeSemantics(
                child: ListTile(
                  leading: const Text('test'),
                  onTap: () {
                    onChanged(!value);
                  },
                  trailing: Switch(value: value, onChanged: onChanged),
                ),
              ),
            );
          },
        ),
      ),
    );
    await tester.tap(find.byType(MergeSemantics));
    final RenderObject object = tester.firstRenderObject(find.byType(MergeSemantics));

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

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

  testWidgets('Switch.adaptive', (WidgetTester tester) async {
    var value = false;
    const activeTrackColor = Color(0xffff1200);
    const inactiveTrackColor = Color(0xffff12ff);
    const thumbColor = Color(0xffffff00);
    const focusColor = Color(0xff00ff00);

    Widget buildFrame(TargetPlatform platform) {
      return MaterialApp(
        theme: ThemeData(platform: platform),
        home: StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return Material(
              child: Center(
                child: Switch.adaptive(
                  value: value,
                  activeColor: activeTrackColor,
                  inactiveTrackColor: inactiveTrackColor,
                  thumbColor: const MaterialStatePropertyAll<Color?>(thumbColor),
                  focusColor: focusColor,
                  onChanged: (bool newValue) {
                    setState(() {
                      value = newValue;
                    });
                  },
                ),
              ),
            );
          },
        ),
      );
    }

    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      value = false;
      await tester.pumpWidget(buildFrame(platform));
      expect(find.byType(Switch), findsOneWidget, reason: 'on ${platform.name}');
      expect(find.byType(CupertinoSwitch), findsNothing);

      final Switch adaptiveSwitch = tester.widget(find.byType(Switch));
      expect(adaptiveSwitch.activeColor, activeTrackColor, reason: 'on ${platform.name}');
      expect(adaptiveSwitch.inactiveTrackColor, inactiveTrackColor, reason: 'on ${platform.name}');
      expect(
        adaptiveSwitch.thumbColor?.resolve(<WidgetState>{}),
        thumbColor,
        reason: 'on ${platform.name}',
      );
      expect(adaptiveSwitch.focusColor, focusColor, reason: 'on ${platform.name}');

      expect(value, isFalse, reason: 'on ${platform.name}');
      await tester.tap(find.byType(Switch));
      expect(value, isTrue, reason: 'on ${platform.name}');
    }

    for (final platform in <TargetPlatform>[
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.linux,
      TargetPlatform.windows,
    ]) {
      value = false;
      await tester.pumpWidget(buildFrame(platform));
      await tester.pumpAndSettle(); // Finish the theme change animation.
      expect(find.byType(CupertinoSwitch), findsNothing);
      expect(value, isFalse, reason: 'on ${platform.name}');
      await tester.tap(find.byType(Switch));
      expect(value, isTrue, reason: 'on ${platform.name}');
    }
  });

  testWidgets('Switch.adaptive default mouse cursor(Cupertino)', (WidgetTester tester) async {
    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      await tester.pumpWidget(buildAdaptiveSwitch(platform: platform, value: false));
      final Size switchSize = tester.getSize(find.byType(Switch));
      expect(switchSize, const Size(60.0, 48.0));
      final TestGesture gesture = await tester.createGesture(
        kind: PointerDeviceKind.mouse,
        pointer: 1,
      );
      await gesture.addPointer(location: tester.getCenter(find.byType(Switch)));
      addTearDown(gesture.removePointer);
      await tester.pump();
      await gesture.moveTo(tester.getCenter(find.byType(Switch)));
      expect(
        RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
        kIsWeb ? SystemMouseCursors.click : SystemMouseCursors.basic,
      );

      await tester.pumpWidget(buildAdaptiveSwitch(platform: platform));
      expect(
        RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
        kIsWeb ? SystemMouseCursors.click : SystemMouseCursors.basic,
      );

      // Test disabled switch.
      await tester.pumpWidget(
        buildAdaptiveSwitch(platform: platform, enabled: false, value: false),
      );
      expect(
        RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1),
        SystemMouseCursors.basic,
      );
      await gesture.removePointer(location: tester.getCenter(find.byType(Switch)));
      await tester.pump();
    }
  });

  testWidgets('Switch.adaptive default thumb/track color and size(Cupertino)', (
    WidgetTester tester,
  ) async {
    const Color thumbColor = Colors.white;
    const inactiveTrackColor = Color.fromARGB(40, 120, 120, 128); // Default inactive track color.
    const activeTrackColor = Color.fromARGB(255, 52, 199, 89); // Default active track color.
    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      // Switches have same sizes on both platform but they are more compact on macOS.
      final trackRRect = platform == TargetPlatform.iOS
          ? RRect.fromLTRBR(4.5, 8.5, 55.5, 39.5, const Radius.circular(15.5))
          : RRect.fromLTRBR(4.5, 4.5, 55.5, 35.5, const Radius.circular(15.5));
      final inactiveThumbRRect = platform == TargetPlatform.iOS
          ? RRect.fromLTRBR(6.0, 10.0, 34.0, 38.0, const Radius.circular(14.0))
          : RRect.fromLTRBR(6.0, 6.0, 34.0, 34.0, const Radius.circular(14.0));
      final activeThumbRRect = platform == TargetPlatform.iOS
          ? RRect.fromLTRBR(26.0, 10.0, 54.0, 38.0, const Radius.circular(14.0))
          : RRect.fromLTRBR(26.0, 6.0, 54.0, 34.0, const Radius.circular(14.0));
      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildAdaptiveSwitch(platform: platform, value: false));
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: inactiveTrackColor,
            rrect: trackRRect,
          ) // Default cupertino inactive track color
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: thumbColor, rrect: inactiveThumbRRect),
        reason: 'Inactive enabled switch should have default track and thumb color',
      );
      expect(find.byType(Opacity), findsOneWidget);
      expect(tester.widget<Opacity>(find.byType(Opacity)).opacity, 1.0);

      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildAdaptiveSwitch(platform: platform));
      await tester.pump();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: activeTrackColor,
            rrect: trackRRect,
          ) // Default cupertino active track color
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: thumbColor, rrect: activeThumbRRect),
        reason: 'Active enabled switch should have default track and thumb color',
      );
      expect(find.byType(Opacity), findsOneWidget);
      expect(tester.widget<Opacity>(find.byType(Opacity)).opacity, 1.0);

      // Test disabled switch.
      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(platform: platform, enabled: false, value: false),
      );
      await tester.pump();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: inactiveTrackColor,
            rrect: trackRRect,
          ) // Default cupertino inactive track color
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: thumbColor, rrect: inactiveThumbRRect),
        reason: 'Inactive disabled switch should have default track and thumb color',
      );
      expect(find.byType(Opacity), findsOneWidget);
      expect(tester.widget<Opacity>(find.byType(Opacity)).opacity, 0.5);

      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildAdaptiveSwitch(platform: platform, enabled: false));
      await tester.pump();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: activeTrackColor,
            rrect: trackRRect,
          ) // Default cupertino active track color
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: thumbColor, rrect: activeThumbRRect),
        reason: 'Active disabled switch should have default track and thumb color',
      );
      expect(find.byType(Opacity), findsOneWidget);
      expect(tester.widget<Opacity>(find.byType(Opacity)).opacity, 0.5);
    }
  });

  testWidgets('Default Switch.adaptive are not affected by '
      'ThemeData.switchThemeData on iOS/macOS', (WidgetTester tester) async {
    const Color defaultThumbColor = Colors.white;
    const defaultInactiveTrackColor = Color.fromARGB(40, 120, 120, 128);
    const defaultActiveTrackColor = Color.fromARGB(255, 52, 199, 89);
    const Color updatedThumbColor = Colors.red;
    const Color updatedTrackColor = Colors.green;
    const overallSwitchTheme = SwitchThemeData(
      thumbColor: MaterialStatePropertyAll<Color>(updatedThumbColor),
      trackColor: MaterialStatePropertyAll<Color>(updatedTrackColor),
    );
    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(platform: platform, overallSwitchThemeData: overallSwitchTheme),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultActiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Active enabled switch should still have default track and thumb color',
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(
          platform: platform,
          value: false,
          overallSwitchThemeData: overallSwitchTheme,
        ),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultInactiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Inactive enabled switch should have default track and thumb color',
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(
          platform: platform,
          enabled: false,
          value: false,
          overallSwitchThemeData: overallSwitchTheme,
        ),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultInactiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Inactive disabled switch should have default track and thumb color',
      );
    }

    await tester.pumpWidget(Container());
    await tester.pumpWidget(
      buildAdaptiveSwitch(
        platform: TargetPlatform.android,
        overallSwitchThemeData: overallSwitchTheme,
      ),
    );
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(color: Color(updatedTrackColor.value))
        ..rrect()
        ..rrect(color: Color(updatedThumbColor.value)),
      reason: 'Switch.adaptive is affected by SwitchTheme on other platforms',
    );
  });

  testWidgets('Default Switch.adaptive are not affected by '
      'SwitchThemeData on iOS/macOS', (WidgetTester tester) async {
    const Color defaultThumbColor = Colors.white;
    const defaultInactiveTrackColor = Color.fromARGB(40, 120, 120, 128);
    const defaultActiveTrackColor = Color.fromARGB(255, 52, 199, 89);
    const Color updatedThumbColor = Colors.red;
    const Color updatedTrackColor = Colors.green;
    const switchTheme = SwitchThemeData(
      thumbColor: MaterialStatePropertyAll<Color>(updatedThumbColor),
      trackColor: MaterialStatePropertyAll<Color>(updatedTrackColor),
    );
    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(platform: platform, switchThemeData: switchTheme),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultActiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Active enabled switch should still have default track and thumb color',
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(platform: platform, value: false, switchThemeData: switchTheme),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultInactiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Inactive enabled switch should have default track and thumb color',
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(
          platform: platform,
          enabled: false,
          value: false,
          switchThemeData: switchTheme,
        ),
      );
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: defaultInactiveTrackColor)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000)) // Thumb border color(only cupertino)
          ..rrect(color: defaultThumbColor),
        reason: 'Inactive disabled switch should have default track and thumb color',
      );
    }

    await tester.pumpWidget(Container());
    await tester.pumpWidget(
      buildAdaptiveSwitch(platform: TargetPlatform.android, switchThemeData: switchTheme),
    );
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(color: Color(updatedTrackColor.value))
        ..rrect()
        ..rrect(color: Color(updatedThumbColor.value)),
      reason: 'Switch.adaptive is affected by SwitchTheme on other platforms',
    );
  });

  testWidgets('Override default adaptive SwitchThemeData on iOS/macOS', (
    WidgetTester tester,
  ) async {
    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(
          platform: platform,
          switchThemeData: const SwitchThemeData(
            thumbColor: MaterialStatePropertyAll<Color>(Colors.yellow),
            trackColor: MaterialStatePropertyAll<Color>(Colors.brown),
          ),
          switchThemeAdaptation: const _SwitchThemeAdaptation(),
        ),
      );

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: Color(Colors.deepPurple.value))
          ..rrect()
          ..rrect()
          ..rrect()
          ..rrect()
          ..rrect(color: Color(Colors.lightGreen.value)),
      );
    }

    // Other platforms should not be affected by the adaptive switch theme.
    for (final platform in <TargetPlatform>[
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.linux,
      TargetPlatform.windows,
    ]) {
      await tester.pumpWidget(Container());
      await tester.pumpWidget(
        buildAdaptiveSwitch(
          platform: platform,
          switchThemeData: const SwitchThemeData(
            thumbColor: MaterialStatePropertyAll<Color>(Colors.yellow),
            trackColor: MaterialStatePropertyAll<Color>(Colors.brown),
          ),
          switchThemeAdaptation: const _SwitchThemeAdaptation(),
        ),
      );

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: Color(Colors.brown.value))
          ..rrect()
          ..rrect(color: Color(Colors.yellow.value)),
      );
    }
  });

  testWidgets('Switch.adaptive default focus color(Cupertino)', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    final node = FocusNode();
    addTearDown(node.dispose);
    await tester.pumpWidget(
      buildAdaptiveSwitch(platform: TargetPlatform.macOS, autofocus: true, focusNode: node),
    );
    await tester.pumpAndSettle();
    expect(node.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(color: const Color(0xff34c759)) // Track color
        ..rrect()
        ..rrect(
          color: const Color(0xcc6ef28f),
          strokeWidth: 3.5,
          style: PaintingStyle.stroke,
        ) // Focused outline
        ..rrect()
        ..rrect()
        ..rrect()
        ..rrect(color: const Color(0xffffffff)), // Thumb color
    );

    await tester.pumpWidget(
      buildAdaptiveSwitch(
        platform: TargetPlatform.macOS,
        autofocus: true,
        focusNode: node,
        focusColor: Colors.red,
      ),
    );
    await tester.pumpAndSettle();
    expect(node.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(color: const Color(0xff34c759)) // Track color
        ..rrect()
        ..rrect(
          color: Color(Colors.red.value),
          strokeWidth: 3.5,
          style: PaintingStyle.stroke,
        ) // Focused outline
        ..rrect()
        ..rrect()
        ..rrect()
        ..rrect(color: const Color(0xffffffff)), // Thumb color
    );
  });

  testWidgets('Material2 - Switch is focusable and has correct focus color', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Switch(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  focusColor: Colors.orange[500],
                  autofocus: true,
                  focusNode: focusNode,
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..circle(color: Colors.orange[500])
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xff2196f3)),
    );

    // Check the false value.
    value = false;
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x52000000),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..circle(color: Colors.orange[500])
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xfffafafa)),
    );

    // Check what happens when disabled.
    value = false;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x1f000000),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xffbdbdbd)),
    );

    focusNode.dispose();
  });

  testWidgets('Material3 - Switch is focusable and has correct focus color', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: themeData,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Switch(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  focusColor: Colors.orange[500],
                  autofocus: true,
                  focusNode: focusNode,
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    // active, enabled switch
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..circle(color: Colors.orange[500]),
    );

    // Check the false value: inactive enabled switch
    value = false;
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.outline,
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..circle(color: Colors.orange[500]),
    );

    // Check what happens when disabled: inactive disabled switch.
    value = false;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..rrect(color: Color.alphaBlend(colors.onSurface.withOpacity(0.38), colors.surface)),
    );

    focusNode.dispose();
  });

  testWidgets('Switch 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: Switch(
              value: true,
              onChanged: (bool newValue) {},
              focusColor: Colors.orange[500],
              autofocus: true,
              splashRadius: splashRadius,
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..circle(color: Colors.orange[500], radius: splashRadius),
    );
  });

  testWidgets('Material2 - Switch can be hovered and has correct hover color', (
    WidgetTester tester,
  ) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Switch(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  hoverColor: Colors.orange[500],
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xff2196f3)),
    );

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

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..circle(color: Colors.orange[500])
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xff2196f3)),
    );

    // Check what happens when disabled.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x1f000000),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: const Color(0xffbdbdbd)),
    );
  });

  testWidgets('Material3 - Switch can be hovered and has correct hover color', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: themeData,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Switch(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  hoverColor: Colors.orange[500],
                );
              },
            ),
          ),
        ),
      );
    }

    // active enabled switch
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: colors.onPrimary),
    );

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

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..circle(color: Colors.orange[500]),
    );

    // Check what happens for disabled active switch
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: colors.surface.withOpacity(1.0)),
    );
  });

  testWidgets('Switch can be toggled by keyboard shortcuts', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Switch(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  focusColor: Colors.orange[500],
                  autofocus: true,
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pumpAndSettle();
    // On web, switches don't respond to the enter key.
    expect(value, kIsWeb ? isTrue : isFalse);
    await tester.sendKeyEvent(LogicalKeyboardKey.enter);
    await tester.pumpAndSettle();
    expect(value, isTrue);
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    expect(value, isFalse);
    await tester.sendKeyEvent(LogicalKeyboardKey.space);
    await tester.pumpAndSettle();
    expect(value, isTrue);
  });

  testWidgets('Switch changes mouse cursor when hovered', (WidgetTester tester) async {
    // Test Switch.adaptive() constructor
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Align(
            alignment: Alignment.topLeft,
            child: Material(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Switch.adaptive(
                  mouseCursor: SystemMouseCursors.text,
                  value: true,
                  onChanged: (_) {},
                ),
              ),
            ),
          ),
        ),
      ),
    );

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

    await tester.pump();

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

    // Test Switch() constructor
    await tester.pumpWidget(
      MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Align(
            alignment: Alignment.topLeft,
            child: Material(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Switch(mouseCursor: SystemMouseCursors.text, value: true, onChanged: (_) {}),
              ),
            ),
          ),
        ),
      ),
    );

    await gesture.moveTo(tester.getCenter(find.byType(Switch)));
    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: Switch(value: true, onChanged: (_) {}),
              ),
            ),
          ),
        ),
      ),
    );

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

    // 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: Switch(value: true, onChanged: null),
              ),
            ),
          ),
        ),
      ),
    );

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

    await tester.pumpAndSettle();
  });

  testWidgets('Material switch should not recreate its render object when disabled', (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/61247.
    var value = true;
    var enabled = true;
    late StateSetter stateSetter;
    await tester.pumpWidget(
      Theme(
        data: theme,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              stateSetter = setState;
              return Material(
                child: Center(
                  child: Switch(
                    value: value,
                    onChanged: !enabled
                        ? null
                        : (bool newValue) {
                            setState(() {
                              value = newValue;
                            });
                          },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final ToggleableStateMixin oldSwitchState = tester.state(
      find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == '_MaterialSwitch'),
    );

    stateSetter(() {
      value = false;
    });
    await tester.pump();
    // Disable the switch when the implicit animation begins.
    stateSetter(() {
      enabled = false;
    });
    await tester.pump();

    final ToggleableStateMixin updatedSwitchState = tester.state(
      find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == '_MaterialSwitch'),
    );

    expect(updatedSwitchState.isInteractive, false);
    expect(updatedSwitchState, oldSwitchState);
    expect(updatedSwitchState.position.isCompleted, false);
    expect(updatedSwitchState.position.isDismissed, false);
  });

  testWidgets('Material2 - Switch thumb color resolves in active/enabled states', (
    WidgetTester tester,
  ) async {
    const activeEnabledThumbColor = Color(0xFF000001);
    const activeDisabledThumbColor = Color(0xFF000002);
    const inactiveEnabledThumbColor = Color(0xFF000003);
    const inactiveDisabledThumbColor = Color(0xFF000004);

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledThumbColor;
        }
        return inactiveDisabledThumbColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledThumbColor;
      }
      return inactiveEnabledThumbColor;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                thumbColor: thumbColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: inactiveDisabledThumbColor),
      reason: 'Inactive disabled switch should default track and custom thumb color',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: activeDisabledThumbColor),
      reason: 'Active disabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x52000000), // Black with 32% opacity,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: inactiveEnabledThumbColor),
      reason: 'Inactive enabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: inactiveDisabledThumbColor),
      reason: 'Inactive disabled switch should match these colors',
    );
  });

  testWidgets('Material3 - Switch thumb color resolves in active/enabled states', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;
    const activeEnabledThumbColor = Color(0xFF000001);
    const activeDisabledThumbColor = Color(0xFF000002);
    const inactiveEnabledThumbColor = Color(0xFF000003);
    const inactiveDisabledThumbColor = Color(0xFF000004);

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledThumbColor;
        }
        return inactiveDisabledThumbColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledThumbColor;
      }
      return inactiveEnabledThumbColor;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return Theme(
        data: themeData,
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                thumbColor: thumbColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect(
          style: PaintingStyle.stroke,
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(5.0, 9.0, 55.0, 39.0, const Radius.circular(16.0)),
        )
        ..rrect(color: inactiveDisabledThumbColor),
      reason: 'Inactive disabled switch should default track and custom thumb color',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: activeDisabledThumbColor),
      reason: 'Active disabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.surfaceContainerHighest,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: inactiveEnabledThumbColor),
      reason: 'Inactive enabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: activeEnabledThumbColor),
      reason: 'Active enabled switch should match these colors',
    );
  });

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

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredThumbColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedThumbColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch() {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: Switch(
              focusNode: focusNode,
              autofocus: true,
              value: true,
              thumbColor: thumbColor,
              onChanged: (_) {},
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..circle() // Radial reaction
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: focusedThumbColor),
      reason: 'Inactive disabled switch should default track and custom thumb color',
    );

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

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: const Color(0x802196f3),
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..circle()
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: hoveredThumbColor),
      reason: 'Inactive disabled switch should default track and custom thumb color',
    );

    focusNode.dispose();
  });

  testWidgets('Material3 - Switch thumb color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final ColorScheme colors = themeData.colorScheme;
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredThumbColor = Color(0xFF000001);
    const focusedThumbColor = Color(0xFF000002);

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredThumbColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedThumbColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch() {
      return MaterialApp(
        theme: themeData,
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                focusNode: focusNode,
                autofocus: true,
                value: true,
                thumbColor: thumbColor,
                onChanged: (_) {},
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..circle(color: colors.primary.withOpacity(0.1))
        ..rrect(color: focusedThumbColor),
      reason: 'active enabled switch should default track and custom thumb color',
    );

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

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: colors.primary,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..circle(color: colors.primary.withOpacity(0.08))
        ..rrect(color: hoveredThumbColor),
      reason: 'active enabled switch should default track and custom thumb color',
    );

    focusNode.dispose();
  });

  testWidgets('Material2 - Track color resolves in active/enabled states', (
    WidgetTester tester,
  ) async {
    const activeEnabledTrackColor = Color(0xFF000001);
    const activeDisabledTrackColor = Color(0xFF000002);
    const inactiveEnabledTrackColor = Color(0xFF000003);
    const inactiveDisabledTrackColor = Color(0xFF000004);

    Color getTrackColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledTrackColor;
        }
        return inactiveDisabledTrackColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledTrackColor;
      }
      return inactiveEnabledTrackColor;
    }

    final WidgetStateProperty<Color> trackColor = WidgetStateColor.resolveWith(getTrackColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Material(
          child: Center(
            child: Switch(
              trackColor: trackColor,
              value: active,
              onChanged: enabled ? (_) {} : null,
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: inactiveDisabledTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Inactive disabled switch track should use this value',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: activeDisabledTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Active disabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: inactiveEnabledTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Inactive enabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: inactiveDisabledTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Inactive disabled switch should match these colors',
    );
  });

  testWidgets('Material3 - Track color resolves in active/enabled states', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    const activeEnabledTrackColor = Color(0xFF000001);
    const activeDisabledTrackColor = Color(0xFF000002);
    const inactiveEnabledTrackColor = Color(0xFF000003);
    const inactiveDisabledTrackColor = Color(0xFF000004);

    Color getTrackColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        if (states.contains(WidgetState.selected)) {
          return activeDisabledTrackColor;
        }
        return inactiveDisabledTrackColor;
      }
      if (states.contains(WidgetState.selected)) {
        return activeEnabledTrackColor;
      }
      return inactiveEnabledTrackColor;
    }

    final WidgetStateProperty<Color> trackColor = WidgetStateColor.resolveWith(getTrackColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return Theme(
        data: themeData,
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                trackColor: trackColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: false));

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: inactiveDisabledTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Inactive disabled switch track should use this value',
    );

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: activeDisabledTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Active disabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: false));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: inactiveEnabledTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Inactive enabled switch should match these colors',
    );

    await tester.pumpWidget(buildSwitch(enabled: true, active: true));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: activeEnabledTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Active enabled switch should match these colors',
    );
  });

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

    Color getTrackColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredTrackColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedTrackColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> trackColor = WidgetStateColor.resolveWith(getTrackColor);

    Widget buildSwitch() {
      return MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                focusNode: focusNode,
                autofocus: true,
                value: true,
                trackColor: trackColor,
                onChanged: (_) {},
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: focusedTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Inactive enabled switch should match these colors',
    );

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

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: hoveredTrackColor,
        rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
      ),
      reason: 'Inactive enabled switch should match these colors',
    );

    focusNode.dispose();
  });

  testWidgets('Material3 - Switch track color resolves in hovered/focused states', (
    WidgetTester tester,
  ) async {
    final themeData = ThemeData();
    final focusNode = FocusNode(debugLabel: 'Switch');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    const hoveredTrackColor = Color(0xFF000001);
    const focusedTrackColor = Color(0xFF000002);

    Color getTrackColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.hovered)) {
        return hoveredTrackColor;
      }
      if (states.contains(WidgetState.focused)) {
        return focusedTrackColor;
      }
      return Colors.transparent;
    }

    final WidgetStateProperty<Color> trackColor = WidgetStateColor.resolveWith(getTrackColor);

    Widget buildSwitch() {
      return Theme(
        data: themeData,
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                focusNode: focusNode,
                autofocus: true,
                value: true,
                trackColor: trackColor,
                onChanged: (_) {},
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch());
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: focusedTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Active enabled switch should match these colors',
    );

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

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints..rrect(
        color: hoveredTrackColor,
        rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
      ),
      reason: 'Active enabled switch should match these colors',
    );

    focusNode.dispose();
  });

  testWidgets('Material2 - Switch thumb color is blended against surface color', (
    WidgetTester tester,
  ) async {
    final Color activeDisabledThumbColor = Colors.blue.withOpacity(.60);
    final theme = ThemeData.light(useMaterial3: false);

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        return activeDisabledThumbColor;
      }
      return Colors.black;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return Directionality(
        textDirection: TextDirection.rtl,
        child: Theme(
          data: theme,
          child: Material(
            child: Center(
              child: Switch(
                thumbColor: thumbColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));

    final Color expectedThumbColor = Color.alphaBlend(
      activeDisabledThumbColor,
      theme.colorScheme.surface,
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: Colors.black12,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: expectedThumbColor),
      reason: 'Active disabled thumb color should be blended on top of surface color',
    );
  });

  testWidgets('Material3 - Switch thumb color is blended against surface color', (
    WidgetTester tester,
  ) async {
    final Color activeDisabledThumbColor = Colors.blue.withOpacity(.60);
    final theme = ThemeData();
    final ColorScheme colors = theme.colorScheme;

    Color getThumbColor(Set<WidgetState> states) {
      if (states.contains(WidgetState.disabled)) {
        return activeDisabledThumbColor;
      }
      return Colors.black;
    }

    final WidgetStateProperty<Color> thumbColor = WidgetStateColor.resolveWith(getThumbColor);

    Widget buildSwitch({required bool enabled, required bool active}) {
      return Directionality(
        textDirection: TextDirection.rtl,
        child: Theme(
          data: theme,
          child: Material(
            child: Center(
              child: Switch(
                thumbColor: thumbColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(enabled: false, active: true));

    final Color expectedThumbColor = Color.alphaBlend(
      activeDisabledThumbColor,
      theme.colorScheme.surface,
    );

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: colors.onSurface.withOpacity(0.12),
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: expectedThumbColor),
      reason: 'Active disabled thumb color should be blended on top of surface color',
    );
  });

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

    const activeThumbColor = Color(0xFF000000);
    const inactiveThumbColor = Color(0xFF000010);
    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;

    Widget buildSwitch({bool active = false, bool focused = false, bool useOverlay = true}) {
      return MaterialApp(
        theme: theme,
        home: Scaffold(
          body: Switch(
            focusNode: focusNode,
            autofocus: focused,
            value: active,
            onChanged: (_) {},
            thumbColor: WidgetStateProperty.resolveWith<Color>((Set<WidgetState> states) {
              if (states.contains(WidgetState.selected)) {
                return activeThumbColor;
              }
              return inactiveThumbColor;
            }),
            overlayColor: useOverlay ? WidgetStateProperty.resolveWith(getOverlayColor) : null,
            hoverColor: hoverColor,
            focusColor: focusColor,
            splashRadius: splashRadius,
          ),
        ),
      );
    }

    // test inactive Switch, and overlayColor is set to null.
    await tester.pumpWidget(buildSwitch(useOverlay: false));
    await tester.press(find.byType(Switch));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: inactiveThumbColor.withAlpha(kRadialReactionAlpha), radius: splashRadius),
      reason: 'Default inactive pressed Switch should have overlay color from thumbColor',
    );

    // test active Switch, and overlayColor is set to null.
    await tester.pumpWidget(buildSwitch(active: true, useOverlay: false));
    await tester.press(find.byType(Switch));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: activeThumbColor.withAlpha(kRadialReactionAlpha), radius: splashRadius),
      reason: 'Default active pressed Switch should have overlay color from thumbColor',
    );

    // test inactive Switch with an overlayColor
    await tester.pumpWidget(buildSwitch());
    await tester.press(find.byType(Switch));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: inactivePressedOverlayColor, radius: splashRadius),
      reason: 'Inactive pressed Switch should have overlay color: $inactivePressedOverlayColor',
    );

    // test active Switch with an overlayColor
    await tester.pumpWidget(buildSwitch(active: true));
    await tester.press(find.byType(Switch));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: activePressedOverlayColor, radius: splashRadius),
      reason: 'Active pressed Switch should have overlay color: $activePressedOverlayColor',
    );

    await tester.pumpWidget(buildSwitch(focused: true));
    await tester.pumpAndSettle();

    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: focusOverlayColor, radius: splashRadius),
      reason: 'Focused Switch 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(find.byType(Switch)));
    await tester.pumpAndSettle();

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect()
        ..circle(color: hoverOverlayColor, radius: splashRadius),
      reason: 'Hovered Switch should use overlay color $hoverOverlayColor over $hoverColor',
    );

    focusNode.dispose();
  });

  testWidgets('Do not crash when widget disappears while pointer is down', (
    WidgetTester tester,
  ) async {
    Widget buildSwitch(bool show) {
      return MaterialApp(
        theme: theme,
        home: Material(
          child: Center(child: show ? Switch(value: true, onChanged: (_) {}) : Container()),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch(true));
    final Offset center = tester.getCenter(find.byType(Switch));
    // 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(buildSwitch(false));
    expect(find.byType(Switch), findsNothing);
    // Release pointer after widget disappeared.
    await gesture.up();
  });

  testWidgets('disabled switch shows tooltip', (WidgetTester tester) async {
    const longPressTooltip = 'long press tooltip';
    const tapTooltip = 'tap tooltip';
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Tooltip(message: longPressTooltip, child: Switch(onChanged: null, value: true)),
        ),
      ),
    );

    // 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(
      const MaterialApp(
        home: Material(
          child: Tooltip(
            triggerMode: TooltipTriggerMode.tap,
            message: tapTooltip,
            child: Switch(onChanged: null, value: true),
          ),
        ),
      ),
    );

    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);
  });

  group('with image', () {
    late ui.Image image;

    setUp(() async {
      image = await createTestImage(width: 100, height: 100);
    });

    testWidgets('thumb image shows up', (WidgetTester tester) async {
      imageCache.clear();
      final provider1 = _TestImageProvider();
      final provider2 = _TestImageProvider();

      expect(provider1.loadCallCount, 0);
      expect(provider2.loadCallCount, 0);

      var value1 = true;
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Switch(
                  activeThumbImage: provider1,
                  inactiveThumbImage: provider2,
                  value: value1,
                  onChanged: (bool val) {
                    setState(() {
                      value1 = val;
                    });
                  },
                ),
              );
            },
          ),
        ),
      );

      expect(provider1.loadCallCount, 1);
      expect(provider2.loadCallCount, 0);
      expect(imageCache.liveImageCount, 1);
      await tester.tap(find.byType(Switch));
      await tester.pumpAndSettle();
      expect(provider1.loadCallCount, 1);
      expect(provider2.loadCallCount, 1);
      expect(imageCache.liveImageCount, 2);
    });

    testWidgets('do not crash when imageProvider completes after Switch is disposed', (
      WidgetTester tester,
    ) async {
      final imageProvider = DelayedImageProvider(image);

      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Material(
            child: Center(
              child: Switch(value: true, onChanged: null, inactiveThumbImage: imageProvider),
            ),
          ),
        ),
      );

      expect(find.byType(Switch), findsOneWidget);

      // Dispose the switch by taking down the tree.
      await tester.pumpWidget(Container());
      expect(find.byType(Switch), findsNothing);

      imageProvider.complete();
      expect(tester.takeException(), isNull);
    });

    testWidgets('do not crash when previous imageProvider completes after Switch is disposed', (
      WidgetTester tester,
    ) async {
      final imageProvider1 = DelayedImageProvider(image);
      final imageProvider2 = DelayedImageProvider(image);

      Future<void> buildSwitch(ImageProvider imageProvider) {
        return tester.pumpWidget(
          MaterialApp(
            theme: theme,
            home: Material(
              child: Center(
                child: Switch(value: true, onChanged: null, inactiveThumbImage: imageProvider),
              ),
            ),
          ),
        );
      }

      await buildSwitch(imageProvider1);
      expect(find.byType(Switch), findsOneWidget);
      // Replace the ImageProvider.
      await buildSwitch(imageProvider2);
      expect(find.byType(Switch), findsOneWidget);

      // Dispose the switch by taking down the tree.
      await tester.pumpWidget(Container());
      expect(find.byType(Switch), findsNothing);

      // Completing the replaced ImageProvider shouldn't crash.
      imageProvider1.complete();
      expect(tester.takeException(), isNull);

      imageProvider2.complete();
      expect(tester.takeException(), isNull);
    });
  });

  group('Switch M3 only tests', () {
    testWidgets('M3 Switch has a 300-millisecond animation in total', (WidgetTester tester) async {
      final theme = ThemeData();
      var value = false;
      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Directionality(
            textDirection: TextDirection.rtl,
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Material(
                  child: Center(
                    child: Switch(
                      value: value,
                      onChanged: (bool newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
      expect(value, isFalse);

      final Rect switchRect = tester.getRect(find.byType(Switch));
      final TestGesture gesture = await tester.startGesture(switchRect.centerLeft);
      await tester.pump();
      await gesture.up();
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 200)); // M2 animation duration
      expect(tester.hasRunningAnimations, true);
      await tester.pump(const Duration(milliseconds: 101));
      expect(tester.hasRunningAnimations, false);
    });

    testWidgets('M3 Switch has a stadium shape in the middle of the track', (
      WidgetTester tester,
    ) async {
      final theme = ThemeData(colorSchemeSeed: Colors.deepPurple);
      var value = false;
      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Directionality(
            textDirection: TextDirection.ltr,
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Material(
                  child: Center(
                    child: Switch(
                      value: value,
                      onChanged: (bool newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
      expect(value, isFalse);

      final Rect switchRect = tester.getRect(find.byType(Switch));
      final TestGesture gesture = await tester.startGesture(switchRect.centerLeft);
      await tester.pump();
      await gesture.up();
      await tester.pump();
      // After 33 milliseconds, the switch thumb moves to the middle
      // and has a stadium shape with a size of (34x22).
      await tester.pump(const Duration(milliseconds: 33));
      expect(tester.hasRunningAnimations, true);

      await expectLater(find.byType(Switch), matchesGoldenFile('switch_test.m3.transition.png'));
    });

    testWidgets('M3 Switch thumb bounces in the end of the animation', (WidgetTester tester) async {
      final theme = ThemeData();
      var value = false;
      await tester.pumpWidget(
        MaterialApp(
          theme: theme,
          home: Directionality(
            textDirection: TextDirection.ltr,
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Material(
                  child: Center(
                    child: Switch(
                      value: value,
                      onChanged: (bool newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
      expect(value, isFalse);

      final Rect switchRect = tester.getRect(find.byType(Switch));
      final TestGesture gesture = await tester.startGesture(switchRect.centerLeft);
      await tester.pump();
      await gesture.up();
      await tester.pump();
      // The value on y axis is greater than 1 when t > 0.375
      // 300 * 0.375 = 112.5
      await tester.pump(const Duration(milliseconds: 113));
      final ToggleableStateMixin state = tester.state<ToggleableStateMixin>(
        find.descendant(
          of: find.byType(Switch),
          matching: find.byWidgetPredicate(
            (Widget widget) => widget.runtimeType.toString() == '_MaterialSwitch',
          ),
        ),
      );
      expect(tester.hasRunningAnimations, true);
      expect(state.position.value, greaterThan(1));
    });

    testWidgets('Switch thumb shows correct pressed color - M3', (WidgetTester tester) async {
      final themeData = ThemeData();
      final ColorScheme colors = themeData.colorScheme;
      Widget buildApp({bool enabled = true, bool value = true}) {
        return MaterialApp(
          theme: themeData,
          home: Material(
            child: Center(
              child: StatefulBuilder(
                builder: (BuildContext context, StateSetter setState) {
                  return Switch(
                    value: value,
                    onChanged: enabled
                        ? (bool newValue) {
                            setState(() {
                              value = newValue;
                            });
                          }
                        : null,
                  );
                },
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildApp());
      await tester.press(find.byType(Switch));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: colors.primary, // track color
            style: PaintingStyle.fill,
          )
          ..rrect(
            color: Colors.transparent, // track outline color
            style: PaintingStyle.stroke,
          )
          ..rrect(
            color: colors.primaryContainer,
            rrect: RRect.fromLTRBR(26.0, 10.0, 54.0, 38.0, const Radius.circular(14.0)),
          ),
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildApp(value: false));
      await tester.press(find.byType(Switch));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: colors.surfaceContainerHighest, // track color
            style: PaintingStyle.fill,
          )
          ..rrect(
            color: colors.outline, // track outline color
            style: PaintingStyle.stroke,
          )
          ..rrect(color: colors.onSurfaceVariant),
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildApp(enabled: false));
      await tester.press(find.byType(Switch));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: colors.onSurface.withOpacity(0.12), // track color
            style: PaintingStyle.fill,
          )
          ..rrect(
            color: Colors.transparent, // track outline color
            style: PaintingStyle.stroke,
          )
          ..rrect(color: colors.surface.withOpacity(1.0)),
      );

      await tester.pumpWidget(Container());
      await tester.pumpWidget(buildApp(enabled: false, value: false));
      await tester.press(find.byType(Switch));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(
            color: colors.surfaceContainerHighest.withOpacity(0.12), // track color
            style: PaintingStyle.fill,
          )
          ..rrect(
            color: colors.onSurface.withOpacity(0.12), // track outline color
            style: PaintingStyle.stroke,
          )
          ..rrect(color: Color.alphaBlend(colors.onSurface.withOpacity(0.38), colors.surface)),
      );
    }, variant: TargetPlatformVariant.mobile());

    testWidgets('Track outline color resolves in active/enabled states', (
      WidgetTester tester,
    ) async {
      const activeEnabledTrackOutlineColor = Color(0xFF000001);
      const activeDisabledTrackOutlineColor = Color(0xFF000002);
      const inactiveEnabledTrackOutlineColor = Color(0xFF000003);
      const inactiveDisabledTrackOutlineColor = Color(0xFF000004);

      Color getTrackOutlineColor(Set<WidgetState> states) {
        if (states.contains(WidgetState.disabled)) {
          if (states.contains(WidgetState.selected)) {
            return activeDisabledTrackOutlineColor;
          }
          return inactiveDisabledTrackOutlineColor;
        }
        if (states.contains(WidgetState.selected)) {
          return activeEnabledTrackOutlineColor;
        }
        return inactiveEnabledTrackOutlineColor;
      }

      final WidgetStateProperty<Color> trackOutlineColor = WidgetStateColor.resolveWith(
        getTrackOutlineColor,
      );

      Widget buildSwitch({required bool enabled, required bool active}) {
        return Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                trackOutlineColor: trackOutlineColor,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildSwitch(enabled: false, active: false));

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: inactiveDisabledTrackOutlineColor, style: PaintingStyle.stroke),
        reason: 'Inactive disabled switch track outline should use this value',
      );

      await tester.pumpWidget(buildSwitch(enabled: false, active: true));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: activeDisabledTrackOutlineColor, style: PaintingStyle.stroke),
        reason: 'Active disabled switch track outline should match these colors',
      );

      await tester.pumpWidget(buildSwitch(enabled: true, active: false));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: inactiveEnabledTrackOutlineColor),
        reason: 'Inactive enabled switch track outline should match these colors',
      );

      await tester.pumpWidget(buildSwitch(enabled: true, active: true));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: activeEnabledTrackOutlineColor),
        reason: 'Active enabled switch track outline should match these colors',
      );
    });

    testWidgets('Switch track outline color resolves in hovered/focused states', (
      WidgetTester tester,
    ) async {
      final focusNode = FocusNode(debugLabel: 'Switch');
      tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
      const hoveredTrackOutlineColor = Color(0xFF000001);
      const focusedTrackOutlineColor = Color(0xFF000002);

      Color getTrackOutlineColor(Set<WidgetState> states) {
        if (states.contains(WidgetState.hovered)) {
          return hoveredTrackOutlineColor;
        }
        if (states.contains(WidgetState.focused)) {
          return focusedTrackOutlineColor;
        }
        return Colors.transparent;
      }

      final WidgetStateProperty<Color> trackOutlineColor = WidgetStateColor.resolveWith(
        getTrackOutlineColor,
      );

      Widget buildSwitch() {
        return Directionality(
          textDirection: TextDirection.rtl,
          child: Material(
            child: Center(
              child: Switch(
                focusNode: focusNode,
                autofocus: true,
                value: true,
                trackOutlineColor: trackOutlineColor,
                onChanged: (_) {},
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildSwitch());
      await tester.pumpAndSettle();
      expect(focusNode.hasPrimaryFocus, isTrue);
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: focusedTrackOutlineColor, style: PaintingStyle.stroke),
        reason: 'Active enabled switch track outline should match this color',
      );

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

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(color: hoveredTrackOutlineColor, style: PaintingStyle.stroke),
        reason: 'Active enabled switch track outline should match this color',
      );

      focusNode.dispose();
    });

    testWidgets('Track outline width resolves in active/enabled states', (
      WidgetTester tester,
    ) async {
      const activeEnabledTrackOutlineWidth = 1.0;
      const activeDisabledTrackOutlineWidth = 2.0;
      const inactiveEnabledTrackOutlineWidth = 3.0;
      const inactiveDisabledTrackOutlineWidth = 4.0;

      double getTrackOutlineWidth(Set<WidgetState> states) {
        if (states.contains(WidgetState.disabled)) {
          if (states.contains(WidgetState.selected)) {
            return activeDisabledTrackOutlineWidth;
          }
          return inactiveDisabledTrackOutlineWidth;
        }
        if (states.contains(WidgetState.selected)) {
          return activeEnabledTrackOutlineWidth;
        }
        return inactiveEnabledTrackOutlineWidth;
      }

      final WidgetStateProperty<double> trackOutlineWidth = WidgetStateProperty.resolveWith(
        getTrackOutlineWidth,
      );

      Widget buildSwitch({required bool enabled, required bool active}) {
        return MaterialApp(
          home: Material(
            child: Center(
              child: Switch(
                trackOutlineWidth: trackOutlineWidth,
                value: active,
                onChanged: enabled ? (_) {} : null,
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildSwitch(enabled: false, active: false));

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: inactiveDisabledTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Inactive disabled switch track outline width should be 4.0',
      );

      await tester.pumpWidget(buildSwitch(enabled: false, active: true));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: activeDisabledTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Active disabled switch track outline width should be 2.0',
      );

      await tester.pumpWidget(buildSwitch(enabled: true, active: false));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: inactiveEnabledTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Inactive enabled switch track outline width should be 3.0',
      );

      await tester.pumpWidget(buildSwitch(enabled: true, active: true));
      await tester.pumpAndSettle();

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: activeEnabledTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Active enabled switch track outline width should be 1.0',
      );
    });

    testWidgets('Switch track outline width resolves in hovered/focused states', (
      WidgetTester tester,
    ) async {
      final focusNode = FocusNode(debugLabel: 'Switch');
      tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
      const hoveredTrackOutlineWidth = 4.0;
      const focusedTrackOutlineWidth = 6.0;

      double getTrackOutlineWidth(Set<WidgetState> states) {
        if (states.contains(WidgetState.hovered)) {
          return hoveredTrackOutlineWidth;
        }
        if (states.contains(WidgetState.focused)) {
          return focusedTrackOutlineWidth;
        }
        return 8.0;
      }

      final WidgetStateProperty<double> trackOutlineWidth = WidgetStateProperty.resolveWith(
        getTrackOutlineWidth,
      );

      Widget buildSwitch() {
        return MaterialApp(
          home: Material(
            child: Center(
              child: Switch(
                focusNode: focusNode,
                autofocus: true,
                value: true,
                trackOutlineWidth: trackOutlineWidth,
                onChanged: (_) {},
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildSwitch());
      await tester.pumpAndSettle();
      expect(focusNode.hasPrimaryFocus, isTrue);
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: focusedTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Active enabled switch track outline width should be 6.0',
      );

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

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill)
          ..rrect(strokeWidth: hoveredTrackOutlineWidth, style: PaintingStyle.stroke),
        reason: 'Active enabled switch track outline width should be 4.0',
      );

      focusNode.dispose();
    });

    testWidgets('Switch can set icon - M3', (WidgetTester tester) async {
      final themeData = ThemeData(
        colorSchemeSeed: const Color(0xff6750a4),
        brightness: Brightness.light,
      );

      WidgetStateProperty<Icon?> thumbIcon(Icon? activeIcon, Icon? inactiveIcon) {
        return WidgetStateProperty.resolveWith<Icon?>((Set<WidgetState> states) {
          if (states.contains(WidgetState.selected)) {
            return activeIcon;
          }
          return inactiveIcon;
        });
      }

      Widget buildSwitch({
        required bool enabled,
        required bool active,
        Icon? activeIcon,
        Icon? inactiveIcon,
      }) {
        return Theme(
          data: themeData,
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: Material(
              child: Center(
                child: Switch(
                  thumbIcon: thumbIcon(activeIcon, inactiveIcon),
                  value: active,
                  onChanged: enabled ? (_) {} : null,
                ),
              ),
            ),
          ),
        );
      }

      // active icon shows when switch is on.
      await tester.pumpWidget(
        buildSwitch(enabled: true, active: true, activeIcon: const Icon(Icons.close)),
      );
      await tester.pumpAndSettle();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect()
          ..rrect()
          ..paragraph(offset: const Offset(32.0, 16.0)),
      );

      // inactive icon shows when switch is off.
      await tester.pumpWidget(
        buildSwitch(enabled: true, active: false, inactiveIcon: const Icon(Icons.close)),
      );
      await tester.pumpAndSettle();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect()
          ..rrect()
          ..rrect()
          ..paragraph(offset: const Offset(12.0, 16.0)),
      );

      // active icon doesn't show when switch is off.
      await tester.pumpWidget(
        buildSwitch(enabled: true, active: false, activeIcon: const Icon(Icons.check)),
      );
      await tester.pumpAndSettle();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect()
          ..rrect()
          ..rrect(),
      );

      // inactive icon doesn't show when switch is on.
      await tester.pumpWidget(
        buildSwitch(enabled: true, active: true, inactiveIcon: const Icon(Icons.check)),
      );
      await tester.pumpAndSettle();
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect()
          ..rrect()
          ..restore(),
      );

      // without icon
      await tester.pumpWidget(buildSwitch(enabled: true, active: false));
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect()
          ..rrect()
          ..rrect()
          ..restore(),
      );
    });
  });

  testWidgets('Switch.adaptive(Cupertino) is focusable and has correct focus color', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode(debugLabel: 'Switch.adaptive');
    addTearDown(focusNode.dispose);
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    var value = true;
    const focusColor = Color(0xffff0000);

    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        theme: ThemeData(platform: TargetPlatform.iOS),
        home: Material(
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Center(
                child: Switch.adaptive(
                  value: value,
                  onChanged: enabled
                      ? (bool newValue) {
                          setState(() {
                            value = newValue;
                          });
                        }
                      : null,
                  focusColor: focusColor,
                  focusNode: focusNode,
                  autofocus: true,
                ),
              );
            },
          ),
        ),
      );
    }

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

    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      find.byType(Switch),
      paints
        ..rrect(color: const Color(0xff34c759))
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: focusColor)
        ..clipRRect()
        ..rrect(color: const Color(0x26000000))
        ..rrect(color: const Color(0x0f000000))
        ..rrect(color: const Color(0x0a000000))
        ..rrect(color: const Color(0xffffffff)),
    );

    // Check the false value.
    value = false;
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();

    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      find.byType(Switch),
      paints
        ..rrect(color: const Color(0x28787880))
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: focusColor)
        ..clipRRect()
        ..rrect(color: const Color(0x26000000))
        ..rrect(color: const Color(0x0f000000))
        ..rrect(color: const Color(0x0a000000))
        ..rrect(color: const Color(0xffffffff)),
    );

    // Check what happens when disabled.
    value = false;
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();

    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      find.byType(Switch),
      paints
        ..rrect(color: const Color(0x28787880))
        ..clipRRect()
        ..rrect(color: const Color(0x26000000))
        ..rrect(color: const Color(0x0f000000))
        ..rrect(color: const Color(0x0a000000))
        ..rrect(color: const Color(0xffffffff)),
    );
  });

  testWidgets('Switch.onFocusChange callback', (WidgetTester tester) async {
    final focusNode = FocusNode(debugLabel: 'Switch');
    var focused = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: Switch(
              value: true,
              focusNode: focusNode,
              onFocusChange: (bool value) {
                focused = value;
              },
              onChanged: (bool newValue) {},
            ),
          ),
        ),
      ),
    );

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

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

    focusNode.dispose();
  });

  testWidgets('Switch.padding is respected', (WidgetTester tester) async {
    Widget buildSwitch({EdgeInsets? padding}) {
      return MaterialApp(
        home: Material(
          child: Center(
            child: Switch(padding: padding, value: true, onChanged: (_) {}),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSwitch());

    expect(tester.getSize(find.byType(Switch)), const Size(60.0, 48.0));

    await tester.pumpWidget(buildSwitch(padding: EdgeInsets.zero));

    expect(tester.getSize(find.byType(Switch)), const Size(52.0, 48.0));

    await tester.pumpWidget(buildSwitch(padding: const EdgeInsets.all(4.0)));

    expect(tester.getSize(find.byType(Switch)), const Size(60.0, 56.0));
  });

  testWidgets('Material2 - Switch activeThumbColor', (WidgetTester tester) async {
    const activeColor = Color(0xffff0000);
    const activeThumbColor = Color(0xff00ff00);
    const activeTrackColor = Color(0xff0000ff);

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                    activeColor: activeColor,
                    activeThumbColor: activeThumbColor,
                    activeTrackColor: activeTrackColor,
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(tester.widget<Switch>(find.byType(Switch)).activeThumbColor, activeThumbColor);

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          color: activeTrackColor,
          rrect: RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0)),
        )
        ..rrect(color: const Color(0x00000000))
        ..rrect(color: const Color(0x33000000))
        ..rrect(color: const Color(0x24000000))
        ..rrect(color: const Color(0x1f000000))
        ..rrect(color: activeThumbColor),
    );
  });

  testWidgets('Material3 - Switch activeThumbColor', (WidgetTester tester) async {
    const activeColor = Color(0xffff0000);
    const activeThumbColor = Color(0xff00ff00);
    const activeTrackColor = Color(0xff0000ff);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                    activeColor: activeColor,
                    activeThumbColor: activeThumbColor,
                    activeTrackColor: activeTrackColor,
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(tester.widget<Switch>(find.byType(Switch)).activeThumbColor, activeThumbColor);

    expect(
      Material.of(tester.element(find.byType(Switch))),
      paints
        ..rrect(
          style: PaintingStyle.fill,
          color: activeTrackColor,
          rrect: RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0)),
        )
        ..rrect()
        ..rrect(color: activeThumbColor),
    );
  });

  testWidgets('Material2 - Switch.adaptive activeThumbColor', (WidgetTester tester) async {
    const activeColor = Color(0xffff0000);
    const activeThumbColor = Color(0xff00ff00);
    const activeTrackColor = Color(0xff0000ff);

    Widget buildFrame(TargetPlatform platform) {
      return MaterialApp(
        key: UniqueKey(),
        theme: ThemeData(platform: platform, useMaterial3: false),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch.adaptive(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                    activeColor: activeColor,
                    activeThumbColor: activeThumbColor,
                    activeTrackColor: activeTrackColor,
                  ),
                ),
              );
            },
          ),
        ),
      );
    }

    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      final trackRRect = platform == TargetPlatform.iOS
          ? RRect.fromLTRBR(4.0, 8.5, 55.0, 39.5, const Radius.circular(15.5))
          : RRect.fromLTRBR(4.0, 4.5, 55.0, 35.5, const Radius.circular(15.5));
      await tester.pumpWidget(buildFrame(platform));
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: activeTrackColor, rrect: trackRRect)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000))
          ..rrect(color: activeThumbColor),
      );
    }

    for (final platform in <TargetPlatform>[
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.linux,
      TargetPlatform.windows,
    ]) {
      final trackRRect = platform == TargetPlatform.fuchsia || platform == TargetPlatform.android
          ? RRect.fromLTRBR(13.0, 17.0, 46.0, 31.0, const Radius.circular(7.0))
          : RRect.fromLTRBR(13.0, 13.0, 46.0, 27.0, const Radius.circular(7.0));
      await tester.pumpWidget(buildFrame(platform));

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: activeTrackColor, rrect: trackRRect)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x33000000))
          ..rrect(color: const Color(0x24000000))
          ..rrect(color: const Color(0x1f000000))
          ..rrect(color: activeThumbColor),
      );
    }
  });

  testWidgets('Material3 - Switch.adaptive activeThumbColor', (WidgetTester tester) async {
    const activeColor = Color(0xffff0000);
    const activeThumbColor = Color(0xff00ff00);
    const activeTrackColor = Color(0xff0000ff);

    Widget buildFrame(TargetPlatform platform) {
      return MaterialApp(
        key: UniqueKey(),
        theme: ThemeData(platform: platform),
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Switch.adaptive(
                    dragStartBehavior: DragStartBehavior.down,
                    value: true,
                    onChanged: (_) {},
                    activeColor: activeColor,
                    activeThumbColor: activeThumbColor,
                    activeTrackColor: activeTrackColor,
                  ),
                ),
              );
            },
          ),
        ),
      );
    }

    for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      final trackRRect = platform == TargetPlatform.iOS
          ? RRect.fromLTRBR(4.5, 8.5, 55.5, 39.5, const Radius.circular(15.5))
          : RRect.fromLTRBR(4.5, 4.5, 55.5, 35.5, const Radius.circular(15.5));
      await tester.pumpWidget(buildFrame(platform));
      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(color: activeTrackColor, rrect: trackRRect)
          ..rrect(color: const Color(0x00000000))
          ..rrect(color: const Color(0x26000000))
          ..rrect(color: const Color(0x0f000000))
          ..rrect(color: const Color(0x0a000000))
          ..rrect(color: activeThumbColor),
      );
    }

    for (final platform in <TargetPlatform>[
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.linux,
      TargetPlatform.windows,
    ]) {
      final trackRRect = platform == TargetPlatform.fuchsia || platform == TargetPlatform.android
          ? RRect.fromLTRBR(4.0, 8.0, 56.0, 40.0, const Radius.circular(16.0))
          : RRect.fromLTRBR(4.0, 4.0, 56.0, 36.0, const Radius.circular(16.0));

      await tester.pumpWidget(buildFrame(platform));

      expect(
        Material.of(tester.element(find.byType(Switch))),
        paints
          ..rrect(style: PaintingStyle.fill, color: activeTrackColor, rrect: trackRRect)
          ..rrect()
          ..rrect(color: activeThumbColor),
      );
    }
  });
}

class DelayedImageProvider extends ImageProvider<DelayedImageProvider> {
  DelayedImageProvider(this.image);

  final ui.Image image;

  final Completer<ImageInfo> _completer = Completer<ImageInfo>();

  @override
  Future<DelayedImageProvider> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<DelayedImageProvider>(this);
  }

  @override
  ImageStreamCompleter loadImage(DelayedImageProvider key, ImageDecoderCallback decode) {
    return OneFrameImageStreamCompleter(_completer.future);
  }

  Future<void> complete() async {
    _completer.complete(ImageInfo(image: image));
  }

  @override
  String toString() => '${describeIdentity(this)}()';
}

class _TestImageProvider extends ImageProvider<Object> {
  _TestImageProvider({ImageStreamCompleter? streamCompleter}) {
    _streamCompleter = streamCompleter ?? OneFrameImageStreamCompleter(_completer.future);
  }

  final Completer<ImageInfo> _completer = Completer<ImageInfo>();
  late ImageStreamCompleter _streamCompleter;

  bool get loadCalled => _loadCallCount > 0;
  int get loadCallCount => _loadCallCount;
  int _loadCallCount = 0;

  @override
  Future<Object> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<_TestImageProvider>(this);
  }

  @override
  void resolveStreamForKey(
    ImageConfiguration configuration,
    ImageStream stream,
    Object key,
    ImageErrorListener handleError,
  ) {
    super.resolveStreamForKey(configuration, stream, key, handleError);
  }

  @override
  ImageStreamCompleter loadImage(Object key, ImageDecoderCallback decode) {
    _loadCallCount += 1;
    return _streamCompleter;
  }

  void complete(ui.Image image) {
    _completer.complete(ImageInfo(image: image));
  }

  void fail(Object exception, StackTrace? stackTrace) {
    _completer.completeError(exception, stackTrace);
  }

  @override
  String toString() => '${describeIdentity(this)}()';
}

Widget buildAdaptiveSwitch({
  required TargetPlatform platform,
  bool enabled = true,
  bool value = true,
  bool autofocus = false,
  FocusNode? focusNode,
  Color? focusColor,
  SwitchThemeData? overallSwitchThemeData,
  SwitchThemeData? switchThemeData,
  Adaptation<SwitchThemeData>? switchThemeAdaptation,
}) {
  final Widget adaptiveSwitch = Switch.adaptive(
    focusNode: focusNode,
    autofocus: autofocus,
    focusColor: focusColor,
    value: value,
    onChanged: enabled ? (_) {} : null,
  );

  return MaterialApp(
    theme: ThemeData(
      platform: platform,
      switchTheme: overallSwitchThemeData,
      adaptations: switchThemeAdaptation == null
          ? null
          : <Adaptation<Object>>[switchThemeAdaptation],
    ),
    home: StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
        return Material(
          child: Center(
            child: switchThemeData == null
                ? adaptiveSwitch
                : SwitchTheme(data: switchThemeData, child: adaptiveSwitch),
          ),
        );
      },
    ),
  );
}

class _SwitchThemeAdaptation extends Adaptation<SwitchThemeData> {
  const _SwitchThemeAdaptation();

  @override
  SwitchThemeData adapt(ThemeData theme, SwitchThemeData defaultValue) {
    switch (theme.platform) {
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.windows:
      case TargetPlatform.linux:
        return defaultValue;
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        return const SwitchThemeData(
          thumbColor: MaterialStatePropertyAll<Color>(Colors.lightGreen),
          trackColor: MaterialStatePropertyAll<Color>(Colors.deepPurple),
        );
    }
  }
}
