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

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/src/physics/utils.dart' show nearEqual;
import 'package:flutter_test/flutter_test.dart';

import '../rendering/mock_canvas.dart';

void main() {
  // Regression test for https://github.com/flutter/flutter/issues/105833
  testWidgets('Drag gesture uses provided gesture settings', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.1, 0.5);
    bool dragStarted = false;
    final Key sliderKey = UniqueKey();

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: GestureDetector(
                    behavior: HitTestBehavior.deferToChild,
                    onHorizontalDragStart: (DragStartDetails details) {
                      dragStarted = true;
                    },
                    child: MediaQuery(
                      data: MediaQuery.of(context).copyWith(gestureSettings: const DeviceGestureSettings(touchSlop: 20)),
                      child: RangeSlider(
                        key: sliderKey,
                        values: values,
                        onChanged: (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    TestGesture drag = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
    await tester.pump(kPressTimeout);

    // Less than configured touch slop, more than default touch slop
    await drag.moveBy(const Offset(19.0, 0));
    await tester.pump();

    expect(values, const RangeValues(0.1, 0.5));
    expect(dragStarted, true);

    dragStarted = false;

    await drag.up();
    await tester.pumpAndSettle();

    drag = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
    await tester.pump(kPressTimeout);

    bool sliderEnd = false;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: GestureDetector(
                    behavior: HitTestBehavior.deferToChild,
                    onHorizontalDragStart: (DragStartDetails details) {
                      dragStarted = true;
                    },
                    child: MediaQuery(
                      data: MediaQuery.of(context).copyWith(gestureSettings: const DeviceGestureSettings(touchSlop: 10)),
                      child: RangeSlider(
                        key: sliderKey,
                        values: values,
                        onChanged: (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        },
                        onChangeEnd: (RangeValues newValues) {
                          sliderEnd = true;
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // More than touch slop.
    await drag.moveBy(const Offset(12.0, 0));

    await drag.up();
    await tester.pumpAndSettle();

    expect(sliderEnd, true);
    expect(dragStarted, false);
  });

  testWidgets('Range Slider can move when tapped (continuous LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // No thumbs get select when tapping between the thumbs outside the touch
    // boundaries
    expect(values, equals(const RangeValues(0.3, 0.7)));
    //  taps at 0.5
    await tester.tap(find.byType(RangeSlider));
    await tester.pump();
    expect(values, equals(const RangeValues(0.3, 0.7)));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // The start thumb is selected when tapping the left inactive track.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.1;
    await tester.tapAt(leftTarget);
    expect(values.start, moreOrLessEquals(0.1, epsilon: 0.01));
    expect(values.end, equals(0.7));

    // The end thumb is selected when tapping the right inactive track.
    await tester.pump();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.9;
    await tester.tapAt(rightTarget);
    expect(values.start, moreOrLessEquals(0.1, epsilon: 0.01));
    expect(values.end, moreOrLessEquals(0.9, epsilon: 0.01));
  });

  testWidgets('Range Slider can move when tapped (continuous RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // No thumbs get select when tapping between the thumbs outside the touch
    // boundaries
    expect(values, equals(const RangeValues(0.3, 0.7)));
    // taps at 0.5
    await tester.tap(find.byType(RangeSlider));
    await tester.pump();
    expect(values, equals(const RangeValues(0.3, 0.7)));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // The end thumb is selected when tapping the left inactive track.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.1;
    await tester.tapAt(leftTarget);
    expect(values.start, 0.3);
    expect(values.end, moreOrLessEquals(0.9, epsilon: 0.01));

    // The start thumb is selected when tapping the right inactive track.
    await tester.pump();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.9;
    await tester.tapAt(rightTarget);
    expect(values.start, moreOrLessEquals(0.1, epsilon: 0.01));
    expect(values.end, moreOrLessEquals(0.9, epsilon: 0.01));
  });

  testWidgets('Range Slider can move when tapped (discrete LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100.0,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // No thumbs get select when tapping between the thumbs outside the touch
    // boundaries
    expect(values, equals(const RangeValues(30, 70)));
    // taps at 0.5
    await tester.tap(find.byType(RangeSlider));
    await tester.pumpAndSettle();
    expect(values, equals(const RangeValues(30, 70)));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // The start thumb is selected when tapping the left inactive track.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.1;
    await tester.tapAt(leftTarget);
    await tester.pumpAndSettle();
    expect(values.start.round(), equals(10));
    expect(values.end.round(), equals(70));

    // The end thumb is selected when tapping the right inactive track.
    await tester.pump();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.9;
    await tester.tapAt(rightTarget);
    await tester.pumpAndSettle();
    expect(values.start.round(), equals(10));
    expect(values.end.round(), equals(90));
  });

  testWidgets('Range Slider can move when tapped (discrete RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // No thumbs get select when tapping between the thumbs outside the touch
    // boundaries
    expect(values, equals(const RangeValues(30, 70)));
    // taps at 0.5
    await tester.tap(find.byType(RangeSlider));
    await tester.pumpAndSettle();
    expect(values, equals(const RangeValues(30, 70)));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // The start thumb is selected when tapping the left inactive track.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.1;
    await tester.tapAt(leftTarget);
    await tester.pumpAndSettle();
    expect(values.start.round(), equals(30));
    expect(values.end.round(), equals(90));

    // The end thumb is selected when tapping the right inactive track.
    await tester.pump();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.9;
    await tester.tapAt(rightTarget);
    await tester.pumpAndSettle();
    expect(values.start.round(), equals(10));
    expect(values.end.round(), equals(90));
  });

  testWidgets('Range Slider thumbs can be dragged to the min and max (continuous LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the start thumb to the min.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, topLeft + (bottomRight - topLeft) * -0.4);
    expect(values.start, equals(0));

    // Drag the end thumb to the max.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, topLeft + (bottomRight - topLeft) * 0.4);
    expect(values.end, equals(1));
  });

  testWidgets('Range Slider thumbs can be dragged to the min and max (continuous RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the end thumb to the max.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, topLeft + (bottomRight - topLeft) * -0.4);
    expect(values.end, equals(1));

    // Drag the start thumb to the min.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, topLeft + (bottomRight - topLeft) * 0.4);
    expect(values.start, equals(0));
  });

  testWidgets('Range Slider thumbs can be dragged to the min and max (discrete LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the start thumb to the min.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, topLeft + (bottomRight - topLeft) * -0.4);
    expect(values.start, equals(0));

    // Drag the end thumb to the max.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, topLeft + (bottomRight - topLeft) * 0.4);
    expect(values.end, equals(100));
  });

  testWidgets('Range Slider thumbs can be dragged to the min and max (discrete RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the end thumb to the max.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, topLeft + (bottomRight - topLeft) * -0.4);
    expect(values.end, equals(100));

    // Drag the start thumb to the min.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, topLeft + (bottomRight - topLeft) * 0.4);
    expect(values.start, equals(0));
  });

  testWidgets('Range Slider thumbs can be dragged together and the start thumb can be dragged apart (continuous LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the start thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the end thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the start thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, -(bottomRight - topLeft) * 0.3);
    expect(values.start, moreOrLessEquals(0.2, epsilon: 0.05));
  });

  testWidgets('Range Slider thumbs can be dragged together and the start thumb can be dragged apart (continuous RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the end thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the start thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the start thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, (bottomRight - topLeft) * 0.3);
    expect(values.start, moreOrLessEquals(0.2, epsilon: 0.05));
  });

  testWidgets('Range Slider thumbs can be dragged together and the start thumb can be dragged apart (discrete LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the start thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.start, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the end thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.end, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the start thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, -(bottomRight - topLeft) * 0.3);
    expect(values.start, moreOrLessEquals(20, epsilon: 0.01));
  });

  testWidgets('Range Slider thumbs can be dragged together and the start thumb can be dragged apart (discrete RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the end thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.end, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the start thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.start, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the start thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, (bottomRight - topLeft) * 0.3);
    expect(values.start, moreOrLessEquals(20, epsilon: 0.01));
  });

  testWidgets('Range Slider thumbs can be dragged together and the end thumb can be dragged apart (continuous LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the start thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the end thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the end thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, (bottomRight - topLeft) * 0.3);
    expect(values.end, moreOrLessEquals(0.8, epsilon: 0.05));
  });

  testWidgets('Range Slider thumbs can be dragged together and the end thumb can be dragged apart (continuous RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the end thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the start thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.05));

    // Drag the end thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, -(bottomRight - topLeft) * 0.3);
    expect(values.end, moreOrLessEquals(0.8, epsilon: 0.05));
  });

  testWidgets('Range Slider thumbs can be dragged together and the end thumb can be dragged apart (discrete LTR)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the start thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.start, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the end thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.end, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the end thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, (bottomRight - topLeft) * 0.3);
    expect(values.end, moreOrLessEquals(80, epsilon: 0.01));
  });

  testWidgets('Range Slider thumbs can be dragged together and the end thumb can be dragged apart (discrete RTL)', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    divisions: 10,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the end thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    expect(values.end, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the start thumb towards the center.
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.start, moreOrLessEquals(50, epsilon: 0.01));

    // Drag the end thumb apart.
    await tester.pumpAndSettle();
    await tester.dragFrom(middle, -(bottomRight - topLeft) * 0.3);
    expect(values.end, moreOrLessEquals(80, epsilon: 0.01));
  });

  testWidgets('Range Slider onChangeEnd and onChangeStart are called on an interaction initiated by tap', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);
    RangeValues? startValues;
    RangeValues? endValues;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                    onChangeStart: (RangeValues newValues) {
                      startValues = newValues;
                    },
                    onChangeEnd: (RangeValues newValues) {
                      endValues = newValues;
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the start thumb towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    expect(startValues, null);
    expect(endValues, null);
    await tester.dragFrom(leftTarget, (bottomRight - topLeft) * 0.2);
    expect(startValues!.start, moreOrLessEquals(30, epsilon: 1));
    expect(startValues!.end, moreOrLessEquals(70, epsilon: 1));
    expect(values.start, moreOrLessEquals(50, epsilon: 1));
    expect(values.end, moreOrLessEquals(70, epsilon: 1));
    expect(endValues!.start, moreOrLessEquals(50, epsilon: 1));
    expect(endValues!.end, moreOrLessEquals(70, epsilon: 1));
  });

  testWidgets('Range Slider onChangeEnd and onChangeStart are called on an interaction initiated by drag', (WidgetTester tester) async {
    RangeValues values = const RangeValues(30, 70);
    late RangeValues startValues;
    late RangeValues endValues;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100,
                    onChanged: (RangeValues newValues) {
                      setState(() {
                        values = newValues;
                      });
                    },
                    onChangeStart: (RangeValues newValues) {
                      startValues = newValues;
                    },
                    onChangeEnd: (RangeValues newValues) {
                      endValues = newValues;
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);

    // Drag the thumbs together.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, (bottomRight - topLeft) * 0.2);
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, (bottomRight - topLeft) * -0.2);
    await tester.pumpAndSettle();
    expect(values.start, moreOrLessEquals(50, epsilon: 1));
    expect(values.end, moreOrLessEquals(51, epsilon: 1));

    // Drag the end thumb to the right.
    final Offset middleTarget = topLeft + (bottomRight - topLeft) * 0.5;
    await tester.dragFrom(middleTarget, (bottomRight - topLeft) * 0.4);
    await tester.pumpAndSettle();
    expect(startValues.start, moreOrLessEquals(50, epsilon: 1));
    expect(startValues.end, moreOrLessEquals(51, epsilon: 1));
    expect(endValues.start, moreOrLessEquals(50, epsilon: 1));
    expect(endValues.end, moreOrLessEquals(90, epsilon: 1));
  });

  ThemeData buildTheme() {
    return ThemeData(
        platform: TargetPlatform.android,
        primarySwatch: Colors.blue,
        sliderTheme: const SliderThemeData(
          disabledThumbColor: Color(0xff000001),
          disabledActiveTickMarkColor: Color(0xff000002),
          disabledActiveTrackColor: Color(0xff000003),
          disabledInactiveTickMarkColor: Color(0xff000004),
          disabledInactiveTrackColor: Color(0xff000005),
          activeTrackColor: Color(0xff000006),
          activeTickMarkColor: Color(0xff000007),
          inactiveTrackColor: Color(0xff000008),
          inactiveTickMarkColor: Color(0xff000009),
          overlayColor: Color(0xff000010),
          thumbColor: Color(0xff000011),
          valueIndicatorColor: Color(0xff000012),
        ),
    );
  }

  Widget buildThemedApp({
    required ThemeData theme,
    Color? activeColor,
    Color? inactiveColor,
    int? divisions,
    bool enabled = true,
  }) {
    RangeValues values = const RangeValues(0.5, 0.75);
    final ValueChanged<RangeValues>? onChanged = !enabled ? null : (RangeValues newValues) {
      values = newValues;
    };
    return MaterialApp(
      home: Directionality(
        textDirection: TextDirection.ltr,
        child: Material(
          child: Center(
            child: Theme(
              data: theme,
              child: RangeSlider(
                values: values,
                labels: RangeLabels(values.start.toStringAsFixed(2), values.end.toStringAsFixed(2)),
                divisions: divisions,
                activeColor: activeColor,
                inactiveColor: inactiveColor,
                onChanged: onChanged,
              ),
            ),
          ),
        ),
      ),
    );
  }

  testWidgets('Range Slider uses the right theme colors for the right shapes for a default enabled slider', (WidgetTester tester) async {
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(theme: theme));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    // Check default theme for enabled widget.
    expect(
      sliderBox,
      paints
        ..rrect(color: sliderTheme.inactiveTrackColor)
        ..rect(color: sliderTheme.activeTrackColor)
        ..rrect(color: sliderTheme.inactiveTrackColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: sliderTheme.thumbColor)
        ..circle(color: sliderTheme.thumbColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes when setting the active color', (WidgetTester tester) async {
    const Color activeColor = Color(0xcafefeed);
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(theme: theme, activeColor: activeColor));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: sliderTheme.inactiveTrackColor)
        ..rect(color: activeColor)
        ..rrect(color: sliderTheme.inactiveTrackColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: activeColor)
        ..circle(color: activeColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes when setting the inactive color', (WidgetTester tester) async {
    const Color inactiveColor = Color(0xdeadbeef);
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(theme: theme, inactiveColor: inactiveColor));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: inactiveColor)
        ..rect(color: sliderTheme.activeTrackColor)
        ..rrect(color: inactiveColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: sliderTheme.thumbColor)
        ..circle(color: sliderTheme.thumbColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes with active and inactive colors', (WidgetTester tester) async {
    const Color activeColor = Color(0xcafefeed);
    const Color inactiveColor = Color(0xdeadbeef);
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(
      theme: theme,
      activeColor: activeColor,
      inactiveColor: inactiveColor,
    ));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: inactiveColor)
        ..rect(color: activeColor)
        ..rrect(color: inactiveColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: activeColor)
        ..circle(color: activeColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes for a discrete slider', (WidgetTester tester) async {
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(theme: theme, divisions: 3));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: sliderTheme.inactiveTrackColor)
        ..rect(color: sliderTheme.activeTrackColor)
        ..rrect(color: sliderTheme.inactiveTrackColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: sliderTheme.inactiveTickMarkColor)
        ..circle(color: sliderTheme.inactiveTickMarkColor)
        ..circle(color: sliderTheme.activeTickMarkColor)
        ..circle(color: sliderTheme.inactiveTickMarkColor)
        ..circle(color: sliderTheme.thumbColor)
        ..circle(color: sliderTheme.thumbColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes for a discrete slider with active and inactive colors', (WidgetTester tester) async {
    const Color activeColor = Color(0xcafefeed);
    const Color inactiveColor = Color(0xdeadbeef);
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;


    await tester.pumpWidget(buildThemedApp(
      theme: theme,
      activeColor: activeColor,
      inactiveColor: inactiveColor,
      divisions: 3,
    ));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: inactiveColor)
        ..rect(color: activeColor)
        ..rrect(color: inactiveColor),
    );
    expect(
      sliderBox,
      paints
        ..circle(color: activeColor)
        ..circle(color: activeColor)
        ..circle(color: inactiveColor)
        ..circle(color: activeColor)
        ..circle(color: activeColor)
        ..circle(color: activeColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledActiveTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.disabledInactiveTrackColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes for a default disabled slider', (WidgetTester tester) async {
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(theme: theme, enabled: false));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: sliderTheme.disabledInactiveTrackColor)
        ..rect(color: sliderTheme.disabledActiveTrackColor)
        ..rrect(color: sliderTheme.disabledInactiveTrackColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.activeTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.inactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes for a disabled slider with active and inactive colors', (WidgetTester tester) async {
    const Color activeColor = Color(0xcafefeed);
    const Color inactiveColor = Color(0xdeadbeef);
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(buildThemedApp(
      theme: theme,
      activeColor: activeColor,
      inactiveColor: inactiveColor,
      enabled: false,
    ));

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    expect(
      sliderBox,
      paints
        ..rrect(color: sliderTheme.disabledInactiveTrackColor)
        ..rect(color: sliderTheme.disabledActiveTrackColor)
        ..rrect(color: sliderTheme.disabledInactiveTrackColor),
    );
    expect(sliderBox, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.activeTrackColor)));
    expect(sliderBox, isNot(paints..rect(color: sliderTheme.inactiveTrackColor)));
  });

  testWidgets('Range Slider uses the right theme colors for the right shapes when the value indicators are showing', (WidgetTester tester) async {
    final ThemeData theme = buildTheme();
    final SliderThemeData sliderTheme = theme.sliderTheme;
    RangeValues values = const RangeValues(0.5, 0.75);

    Widget buildApp({
      Color? activeColor,
      Color? inactiveColor,
      int? divisions,
      bool enabled = true,
    }) {
      final ValueChanged<RangeValues>? onChanged = !enabled ? null : (RangeValues newValues) {
        values = newValues;
      };
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: Theme(
                data: theme,
                child: RangeSlider(
                  values: values,
                  labels: RangeLabels(values.start.toStringAsFixed(2), values.end.toStringAsFixed(2)),
                  divisions: divisions,
                  activeColor: activeColor,
                  inactiveColor: inactiveColor,
                  onChanged: onChanged,
                ),
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(divisions: 3));

    final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));

    final Offset topRight = tester.getTopRight(find.byType(RangeSlider)).translate(-24, 0);
    final TestGesture gesture = await tester.startGesture(topRight);
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();
    expect(values.end, equals(1));
    expect(
      valueIndicatorBox,
      paints
        ..path(color: Colors.black) // shadow
        ..path(color: Colors.black) // shadow
        ..path(color: sliderTheme.valueIndicatorColor)
        ..paragraph()
    );
    await gesture.up();
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();
  });

  testWidgets('Range Slider removes value indicator from overlay if Slider gets disposed without value indicator animation completing.', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.5, 0.75);
    const Color fillColor = Color(0xf55f5f5f);

    Widget buildApp({
      Color? activeColor,
      Color? inactiveColor,
      int? divisions,
      bool enabled = true,
    }) {
      void onChanged(RangeValues newValues) {
        values = newValues;
      }
      return MaterialApp(
        home: Scaffold(
          // The builder is used to pass the context from the MaterialApp widget
          // to the [Navigator]. This context is required in order for the
          // Navigator to work.
          body: Builder(
            builder: (BuildContext context) {
              return Column(
                children: <Widget>[
                  RangeSlider(
                    values: values,
                    labels: RangeLabels(
                      values.start.toStringAsFixed(2),
                      values.end.toStringAsFixed(2),
                    ),
                    divisions: divisions,
                    onChanged: onChanged,
                  ),
                  ElevatedButton(
                    child: const Text('Next'),
                    onPressed: () {
                      Navigator.of(context).pushReplacement(
                        MaterialPageRoute<void>(
                          builder: (BuildContext context) {
                            return ElevatedButton(
                              child: const Text('Inner page'),
                              onPressed: () { Navigator.of(context).pop(); },
                            );
                          },
                        ),
                      );
                    },
                  ),
                ],
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp(divisions: 3));

    final RenderObject valueIndicatorBox = tester.renderObject(find.byType(Overlay));
    final Offset topRight = tester.getTopRight(find.byType(RangeSlider)).translate(-24, 0);
    final TestGesture gesture = await tester.startGesture(topRight);
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();

    expect(
      valueIndicatorBox,
      paints
      // Represents the raised button wth next text.
      ..path(color: Colors.black)
      ..paragraph()
      // Represents the range slider.
      ..path(color: fillColor)
      ..paragraph()
      ..path(color: fillColor)
      ..paragraph(),
    );

    // Represents the Raised Button and Range Slider.
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 6));
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 3));

    await tester.tap(find.text('Next'));
    await tester.pumpAndSettle();

    expect(find.byType(RangeSlider), findsNothing);
    expect(
      valueIndicatorBox,
      isNot(
      paints
        ..path(color: fillColor)
        ..paragraph()
        ..path(color: fillColor)
        ..paragraph(),
      ),
    );

    // Represents the raised button with inner page text.
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));

    // Don't stop holding the value indicator.
    await gesture.up();
    await tester.pumpAndSettle();
  });

  testWidgets('Range Slider top thumb gets stroked when overlapping', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    final ThemeData theme = ThemeData(
      platform: TargetPlatform.android,
      primarySwatch: Colors.blue,
      sliderTheme: const SliderThemeData(
        thumbColor: Color(0xff000001),
        overlappingShapeStrokeColor: Color(0xff000002),
      ),
    );
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Theme(
                    data: theme,
                    child: RangeSlider(
                      values: values,
                      onChanged: (RangeValues newValues) {
                        setState(() {
                          values = newValues;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(RangeSlider));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the thumbs towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.03));
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.03));
    await tester.pumpAndSettle();

    expect(
      sliderBox,
      paints
        ..circle(color: sliderTheme.thumbColor)
        ..circle(color: sliderTheme.overlappingShapeStrokeColor)
        ..circle(color: sliderTheme.thumbColor),
    );
  });

  testWidgets('Range Slider top value indicator gets stroked when overlapping', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    final ThemeData theme = ThemeData(
      platform: TargetPlatform.android,
      primarySwatch: Colors.blue,
      sliderTheme: const SliderThemeData(
        valueIndicatorColor: Color(0xff000001),
        overlappingShapeStrokeColor: Color(0xff000002),
        showValueIndicator: ShowValueIndicator.always,
      ),
    );
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Theme(
                    data: theme,
                    child: RangeSlider(
                      values: values,
                      labels: RangeLabels(values.start.toStringAsFixed(2), values.end.toStringAsFixed(2)),
                      onChanged: (RangeValues newValues) {
                        setState(() {
                          values = newValues;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the thumbs towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    await tester.pumpAndSettle();
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.03));
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.03));
    final TestGesture gesture = await tester.startGesture(middle);
    await tester.pumpAndSettle();

    expect(
      valueIndicatorBox,
      paints
        ..path(color: Colors.black) // shadow
        ..path(color: Colors.black) // shadow
        ..path(color: sliderTheme.valueIndicatorColor)
        ..paragraph(),
    );

    await gesture.up();
  });

  testWidgets('Range Slider top value indicator gets stroked when overlapping with large text scale', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    final ThemeData theme = ThemeData(
      platform: TargetPlatform.android,
      primarySwatch: Colors.blue,
      sliderTheme: const SliderThemeData(
        valueIndicatorColor: Color(0xff000001),
        overlappingShapeStrokeColor: Color(0xff000002),
        showValueIndicator: ShowValueIndicator.always,
      ),
    );
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: const MediaQueryData(textScaleFactor: 2.0),
                child: Material(
                  child: Center(
                    child: Theme(
                      data: theme,
                      child: RangeSlider(
                        values: values,
                        labels: RangeLabels(values.start.toStringAsFixed(2), values.end.toStringAsFixed(2)),
                        onChanged: (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the thumbs towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    await tester.pumpAndSettle();
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.03));
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.03));
    final TestGesture gesture = await tester.startGesture(middle);
    await tester.pumpAndSettle();

    expect(
      valueIndicatorBox,
      paints
        ..path(color: Colors.black) // shadow
        ..path(color: Colors.black) // shadow
        ..path(color: sliderTheme.valueIndicatorColor)
        ..paragraph(),
    );

    await gesture.up();
  });

  testWidgets('Range Slider thumb gets stroked when overlapping', (WidgetTester tester) async {
    RangeValues values = const RangeValues(0.3, 0.7);

    final ThemeData theme = ThemeData(
      platform: TargetPlatform.android,
      primarySwatch: Colors.blue,
      sliderTheme: const SliderThemeData(
        valueIndicatorColor: Color(0xff000001),
        showValueIndicator: ShowValueIndicator.onlyForContinuous,
      ),
    );
    final SliderThemeData sliderTheme = theme.sliderTheme;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: Theme(
                    data: theme,
                    child: RangeSlider(
                      values: values,
                      labels: RangeLabels(values.start.toStringAsFixed(2), values.end.toStringAsFixed(2)),
                      onChanged: (RangeValues newValues) {
                        setState(() {
                          values = newValues;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    // Get the bounds of the track by finding the slider edges and translating
    // inwards by the overlay radius.
    final Offset topLeft = tester.getTopLeft(find.byType(RangeSlider)).translate(24, 0);
    final Offset bottomRight = tester.getBottomRight(find.byType(RangeSlider)).translate(-24, 0);
    final Offset middle = topLeft + bottomRight / 2;

    // Drag the thumbs towards the center.
    final Offset leftTarget = topLeft + (bottomRight - topLeft) * 0.3;
    await tester.dragFrom(leftTarget, middle - leftTarget);
    await tester.pumpAndSettle();
    final Offset rightTarget = topLeft + (bottomRight - topLeft) * 0.7;
    await tester.dragFrom(rightTarget, middle - rightTarget);
    await tester.pumpAndSettle();
    expect(values.start, moreOrLessEquals(0.5, epsilon: 0.03));
    expect(values.end, moreOrLessEquals(0.5, epsilon: 0.03));
    final TestGesture gesture = await tester.startGesture(middle);
    await tester.pumpAndSettle();

    /// The first circle is the thumb, the second one is the overlapping shape
    /// circle, and the last one is the second thumb.
    expect(
      find.byType(RangeSlider),
      paints
        ..circle()
        ..circle(color: sliderTheme.overlappingShapeStrokeColor)
        ..circle(),
    );

    await gesture.up();

    expect(
      find.byType(RangeSlider),
      paints
        ..circle()
        ..circle(color: sliderTheme.overlappingShapeStrokeColor)
        ..circle(),
    );
  });

  // Regression test for https://github.com/flutter/flutter/issues/101868
  testWidgets('RangeSlider.label info should not write to semantic node', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Theme(
          data: ThemeData.light(),
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: Material(
              child: RangeSlider(
                values: const RangeValues(10.0, 12.0),
                max: 100.0,
                onChanged: (RangeValues v) { },
                labels: const RangeLabels('Begin', 'End'),
              ),
            ),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    expect(
      tester.getSemantics(find.byType(RangeSlider)),
      matchesSemantics(
        scopesRoute: true,
        children:<Matcher>[
          matchesSemantics(
            children:  <Matcher>[
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '10%',
                increasedValue: '10%',
                decreasedValue: '5%',
                label: ''
              ),
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '12%',
                increasedValue: '17%',
                decreasedValue: '12%',
                label: ''
              ),
            ],
          ),
        ],
      ),
    );
  });

  testWidgets('Range Slider Semantics - ltr', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Theme(
          data: ThemeData.light(),
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: Material(
              child: RangeSlider(
                values: const RangeValues(10.0, 30.0),
                max: 100.0,
                onChanged: (RangeValues v) { },
              ),
            ),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    final SemanticsNode semanticsNode = tester.getSemantics(find.byType(RangeSlider));
    expect(
      semanticsNode,
      matchesSemantics(
        scopesRoute: true,
        children:<Matcher>[
          matchesSemantics(
            children:  <Matcher>[
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '10%',
                increasedValue: '15%',
                decreasedValue: '5%',
                rect: const Rect.fromLTRB(75.2, 276.0, 123.2, 324.0),
              ),
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '30%',
                increasedValue: '35%',
                decreasedValue: '25%',
                rect: const Rect.fromLTRB(225.6, 276.0, 273.6, 324.0),
              ),
            ],
          ),
        ],
      ),
    );

    // TODO(tahatesser): This is a workaround for matching
    // the semantics node rects by avoiding floating point errors.
    // https://github.com/flutter/flutter/issues/115079
    // Get semantics node rects.
    final List<Rect> rects = <Rect>[];
    semanticsNode.visitChildren((SemanticsNode node) {
      node.visitChildren((SemanticsNode node) {
       // Round rect values to avoid floating point errors.
        rects.add(
          Rect.fromLTRB(
            node.rect.left.roundToDouble(),
            node.rect.top.roundToDouble(),
            node.rect.right.roundToDouble(),
            node.rect.bottom.roundToDouble(),
          ),
        );
        return true;
      });
      return true;
    });
    // Test that the semantics node rect sizes are correct.
    expect(rects, <Rect>[
      const Rect.fromLTRB(75.0, 276.0, 123.0, 324.0),
      const Rect.fromLTRB(226.0, 276.0, 274.0, 324.0)
    ]);
  });

  testWidgets('Range Slider Semantics - rtl', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Theme(
          data: ThemeData.light(),
          child: Directionality(
            textDirection: TextDirection.rtl,
            child: Material(
              child: RangeSlider(
                values: const RangeValues(10.0, 30.0),
                max: 100.0,
                onChanged: (RangeValues v) { },
              ),
            ),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    final SemanticsNode semanticsNode = tester.getSemantics(find.byType(RangeSlider));
    expect(
      semanticsNode,
      matchesSemantics(
        scopesRoute: true,
        children:<Matcher>[
          matchesSemantics(
            children:  <Matcher>[
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '10%',
                increasedValue: '15%',
                decreasedValue: '5%',
              ),
              matchesSemantics(
                isEnabled: true,
                isSlider: true,
                hasEnabledState: true,
                hasIncreaseAction: true,
                hasDecreaseAction: true,
                value: '30%',
                increasedValue: '35%',
                decreasedValue: '25%',
              ),
            ],
          ),
        ],
      ),
    );

    // TODO(tahatesser): This is a workaround for matching
    // the semantics node rects by avoiding floating point errors.
    // https://github.com/flutter/flutter/issues/115079
    // Get semantics node rects.
    final List<Rect> rects = <Rect>[];
    semanticsNode.visitChildren((SemanticsNode node) {
      node.visitChildren((SemanticsNode node) {
        // Round rect values to avoid floating point errors.
        rects.add(
          Rect.fromLTRB(
            node.rect.left.roundToDouble(),
            node.rect.top.roundToDouble(),
            node.rect.right.roundToDouble(),
            node.rect.bottom.roundToDouble(),
          ),
        );
        return true;
      });
      return true;
    });
    // Test that the semantics node rect sizes are correct.
    expect(rects, <Rect>[
      const Rect.fromLTRB(526.0, 276.0, 574.0, 324.0),
      const Rect.fromLTRB(677.0, 276.0, 725.0, 324.0)
    ]);
  });

  testWidgets('Range Slider implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();

    RangeSlider(
      activeColor: Colors.blue,
      divisions: 4,
      inactiveColor: Colors.grey,
      labels: const RangeLabels('lowerValue', 'upperValue'),
      max: 100.0,
      onChanged: null,
      values: const RangeValues(25.0, 75.0),
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
      .map((DiagnosticsNode node) => node.toString()).toList();

    expect(description, <String>[
      'valueStart: 25.0',
      'valueEnd: 75.0',
      'disabled',
      'min: 0.0',
      'max: 100.0',
      'divisions: 4',
      'labelStart: "lowerValue"',
      'labelEnd: "upperValue"',
      'activeColor: MaterialColor(primary value: Color(0xff2196f3))',
      'inactiveColor: MaterialColor(primary value: Color(0xff9e9e9e))',
    ]);
  });

  testWidgets('Range Slider can be painted in a narrower constraint when track shape is RoundedRectRange', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: SizedBox(
                height: 10.0,
                width: 0.0,
                child: RangeSlider(
                  values: const RangeValues(0.25, 0.5),
                  onChanged: null,
                ),
              ),
            ),
          ),
        ),
      ),
    );

    // _RenderRangeSlider is the last render object in the tree.
    final RenderObject renderObject = tester.allRenderObjects.last;

    expect(
      renderObject,
      paints
        // left inactive track RRect
        ..rrect(rrect: RRect.fromLTRBAndCorners(-24.0, 3.0, -12.0, 7.0, topLeft: const Radius.circular(2.0), bottomLeft: const Radius.circular(2.0)))
        // active track RRect
        ..rect(rect: const Rect.fromLTRB(-12.0, 2.0, 0.0, 8.0))
        // right inactive track RRect
        ..rrect(rrect: RRect.fromLTRBAndCorners(0.0, 3.0, 24.0, 7.0, topRight: const Radius.circular(2.0), bottomRight: const Radius.circular(2.0)))
        // thumbs
        ..circle(x: -12.0, y: 5.0, radius: 10.0)
        ..circle(x: 0.0, y: 5.0, radius: 10.0),
    );
  });

  testWidgets('Range Slider can be painted in a narrower constraint when track shape is Rectangular', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          sliderTheme: const SliderThemeData(
            rangeTrackShape: RectangularRangeSliderTrackShape(),
          ),
        ),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: SizedBox(
                height: 10.0,
                width: 0.0,
                child: RangeSlider(
                  values: const RangeValues(0.25, 0.5),
                  onChanged: null,
                ),
              ),
            ),
          ),
        ),
      ),
    );

    // _RenderRangeSlider is the last render object in the tree.
    final RenderObject renderObject = tester.allRenderObjects.last;

    //There should no gap between the inactive track and active track.
    expect(
      renderObject,
      paints
        // left inactive track RRect
        ..rect(rect: const Rect.fromLTRB(-24.0, 3.0, -12.0, 7.0))
        // active track RRect
        ..rect(rect: const Rect.fromLTRB(-12.0, 3.0, 0.0, 7.0))
        // right inactive track RRect
        ..rect(rect: const Rect.fromLTRB(0.0, 3.0, 24.0, 7.0))
        // thumbs
        ..circle(x: -12.0, y: 5.0, radius: 10.0)
        ..circle(x: 0.0, y: 5.0, radius: 10.0),
    );
  });

  testWidgets('Update the divisions and values at the same time for RangeSlider', (WidgetTester tester) async {
    // Regress test for https://github.com/flutter/flutter/issues/65943
    Widget buildFrame(double maxValue) {
      return MaterialApp(
        home: Material(
          child: Center(
            child: RangeSlider(
              values: const RangeValues(5, 8),
              max: maxValue,
              divisions: maxValue.toInt(),
              onChanged: (RangeValues newValue) {},
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(10));

    // _RenderRangeSlider is the last render object in the tree.
    final RenderObject renderObject = tester.allRenderObjects.last;

    // Update the divisions from 10 to 15, the thumbs should be paint at the correct position.
    await tester.pumpWidget(buildFrame(15));
    await tester.pumpAndSettle(); // Finish the animation.

    late Rect activeTrackRect;
    expect(renderObject, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawRect) {
        return false;
      }
      activeTrackRect = arguments[0] as Rect;
      return true;
    }));

    // The 1st thumb should at one-third(5 / 15) of the Slider.
    // The 2nd thumb should at (8 / 15) of the Slider.
    // The left of the active track shape is the position of the 1st thumb.
    // The right of the active track shape is the position of the 2nd thumb.
    // 24.0 is the default margin, (800.0 - 24.0 - 24.0) is the slider's width.
    expect(nearEqual(activeTrackRect.left, (800.0 - 24.0 - 24.0) * (5 / 15) + 24.0, 0.01), true);
    expect(nearEqual(activeTrackRect.right, (800.0 - 24.0 - 24.0) * (8 / 15) + 24.0, 0.01), true);
  });

  testWidgets('RangeSlider changes mouse cursor when hovered', (WidgetTester tester) async {
    const RangeValues values = RangeValues(50, 70);

    // Test default cursor.
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: RangeSlider(
                  values: values,
                  max: 100.0,
                  onChanged: (RangeValues values) {},
                ),
              ),
            ),
          ),
        ),
      ),
    );

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

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

    // Test custom cursor.
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: RangeSlider(
                  values: values,
                  max: 100.0,
                  mouseCursor: const MaterialStatePropertyAll<MouseCursor?>(SystemMouseCursors.text),
                  onChanged: (RangeValues values) {},
                ),
              ),
            ),
          ),
        ),
      ),
    );

    await tester.pump();
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
  });

  testWidgets('RangeSlider MaterialStateMouseCursor resolves correctly', (WidgetTester tester) async {
    RangeValues values = const RangeValues(50, 70);
    const MouseCursor disabledCursor = SystemMouseCursors.basic;
    const MouseCursor hoveredCursor = SystemMouseCursors.grab;
    const MouseCursor draggedCursor = SystemMouseCursors.move;

    Widget buildFrame({ required bool enabled }) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Center(
                  child: MouseRegion(
                  cursor: SystemMouseCursors.forbidden,
                  child: RangeSlider(
                    mouseCursor: MaterialStateProperty.resolveWith<MouseCursor?>(
                      (Set<MaterialState> states) {
                          if (states.contains(MaterialState.disabled)) {
                            return disabledCursor;
                          }
                          if (states.contains(MaterialState.dragged)) {
                            return draggedCursor;
                          }
                          if (states.contains(MaterialState.hovered)) {
                            return hoveredCursor;
                          }

                          return SystemMouseCursors.none;
                        },
                      ),
                      values: values,
                      max: 100.0,
                      onChanged: enabled
                        ? (RangeValues newValues) {
                            setState(() {
                              values = newValues;
                            });
                          }
                        : null,
                      onChangeStart: enabled ? (RangeValues newValues) {} : null,
                      onChangeEnd: enabled ? (RangeValues newValues) {} : null,
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
    await gesture.addPointer(location: Offset.zero);

    await tester.pumpWidget(buildFrame(enabled: false));
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), disabledCursor);

    await tester.pumpWidget(buildFrame(enabled: true));
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.none);

    await gesture.moveTo(tester.getCenter(find.byType(RangeSlider))); // start hover
    await tester.pumpAndSettle();
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), hoveredCursor);

    await tester.timedDrag(
      find.byType(RangeSlider),
      const Offset(20.0, 0.0),
      const Duration(milliseconds: 100),
    );
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), draggedCursor);
  });

  testWidgets('RangeSlider can be hovered and has correct hover color', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    RangeValues values = const RangeValues(50, 70);
    final ThemeData theme = ThemeData();

    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100.0,
                    onChanged: enabled
                      ? (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        }
                      : null,
                  ),
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    // RangeSlider does not have overlay when enabled and not hovered.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: theme.colorScheme.primary.withOpacity(0.12))),
    );

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

    // RangeSlider has overlay when enabled and hovered.
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      paints..circle(color: theme.colorScheme.primary.withOpacity(0.12)),
    );

    // RangeSlider does not have an overlay when disabled and hovered.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: theme.colorScheme.primary.withOpacity(0.12))),
    );
  });

  testWidgets('RangeSlider is draggable and has correct dragged color', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    RangeValues values = const RangeValues(50, 70);
    final ThemeData theme = ThemeData();

    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100.0,
                    onChanged: enabled
                      ? (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        }
                      : null,
                  ),
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    // RangeSlider does not have overlay when enabled and not dragged.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: theme.colorScheme.primary.withOpacity(0.12))),
    );

    // Start dragging.
    final TestGesture drag = await tester.startGesture(tester.getCenter(find.byType(RangeSlider)));
    await tester.pump(kPressTimeout);

    // Less than configured touch slop, more than default touch slop
    await drag.moveBy(const Offset(19.0, 0));
    await tester.pump();

    // RangeSlider has overlay when enabled and dragged.
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      paints..circle(color: theme.colorScheme.primary.withOpacity(0.12)),
    );
  });

  testWidgets('RangeSlider overlayColor supports hovered and dragged states', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    RangeValues values = const RangeValues(50, 70);
    const Color hoverColor = Color(0xffff0000);
    const Color draggedColor = Color(0xff0000ff);

    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: RangeSlider(
                    values: values,
                    max: 100.0,
                    overlayColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
                      if (states.contains(MaterialState.hovered)) {
                        return hoverColor;
                      }
                      if (states.contains(MaterialState.dragged)) {
                        return draggedColor;
                      }

                      return null;
                    }),
                    onChanged: enabled
                      ? (RangeValues newValues) {
                          setState(() {
                            values = newValues;
                          });
                        }
                      : null,
                    onChangeStart: enabled ? (RangeValues newValues) {} : null,
                    onChangeEnd: enabled ? (RangeValues newValues) {} : null,
                  ),
                ),
              );
            },
          ),
        ),
      );
    }
    await tester.pumpWidget(buildApp());

    // RangeSlider does not have overlay when enabled and not hovered.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: hoverColor)),
    );

    // Hover on the range slider but outside the thumb.
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(tester.getTopLeft(find.byType(RangeSlider)));

    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: hoverColor)),
    );

    // Hover on the thumb.
    await gesture.moveTo(tester.getCenter(find.byType(RangeSlider)));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      paints..circle(color: hoverColor),
    );

    // Hover on the slider but outside the thumb.
    await gesture.moveTo(tester.getBottomRight(find.byType(RangeSlider)));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: hoverColor)),
    );

    // Reset range slider values.
    values = const RangeValues(50, 70);

    // RangeSlider does not have overlay when enabled and not dragged.
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: draggedColor)),
    );

    // Start dragging.
    final TestGesture drag = await tester.startGesture(tester.getCenter(find.byType(RangeSlider)));
    await tester.pump(kPressTimeout);

    // Less than configured touch slop, more than default touch slop.
    await drag.moveBy(const Offset(19.0, 0));
    await tester.pump();

    // RangeSlider has overlay when enabled and dragged.
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      paints..circle(color: draggedColor),
    );

    // Stop dragging.
    await drag.up();
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(RangeSlider))),
      isNot(paints..circle(color: draggedColor)),
    );
  });
}
