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

// @dart = 2.8

import 'dart:ui';

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

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

// A thumb shape that also logs its repaint center.
class LoggingThumbShape extends SliderComponentShape {
  LoggingThumbShape(this.log);

  final List<Offset> log;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size(10.0, 10.0);
  }

  @override
  void paint(
    PaintingContext context,
    Offset thumbCenter, {
    Animation<double> activationAnimation,
    Animation<double> enableAnimation,
    bool isEnabled,
    bool isDiscrete,
    bool onActiveTrack,
    TextPainter labelPainter,
    RenderBox parentBox,
    SliderThemeData sliderTheme,
    TextDirection textDirection,
    double value,
    double textScaleFactor,
    Size sizeWithOverflow,
  }) {
    log.add(thumbCenter);
    final Paint thumbPaint = Paint()..color = Colors.red;
    context.canvas.drawCircle(thumbCenter, 5.0, thumbPaint);
  }
}

class TallSliderTickMarkShape extends SliderTickMarkShape {
  @override
  Size getPreferredSize({SliderThemeData sliderTheme, bool isEnabled}) {
    return const Size(10.0, 200.0);
  }

  @override
  void paint(
    PaintingContext context,
    Offset offset, {
    Offset thumbCenter,
    RenderBox parentBox,
    SliderThemeData sliderTheme,
    Animation<double> enableAnimation,
    bool isEnabled,
    TextDirection textDirection,
  }) {
    final Paint paint = Paint()..color = Colors.red;
    context.canvas.drawRect(Rect.fromLTWH(offset.dx, offset.dy, 10.0, 20.0), paint);
  }
}

void main() {
  testWidgets('Slider can move when tapped (LTR)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    double startValue;
    double endValue;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      onChanged: (double newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                      onChangeStart: (double value) {
                        startValue = value;
                      },
                      onChangeEnd: (double value) {
                        endValue = value;
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    expect(startValue, equals(0.0));
    expect(endValue, equals(0.5));
    startValue = null;
    endValue = null;
    await tester.pump(); // No animation should start.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));

    final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey));
    final Offset bottomRight = tester.getBottomRight(find.byKey(sliderKey));

    final Offset target = topLeft + (bottomRight - topLeft) / 4.0;
    await tester.tapAt(target);
    expect(value, closeTo(0.25, 0.05));
    expect(startValue, equals(0.5));
    expect(endValue, closeTo(0.25, 0.05));
    await tester.pump(); // No animation should start.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });

  testWidgets('Slider can move when tapped (RTL)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      onChanged: (double newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    await tester.pump(); // No animation should start.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));

    final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey));
    final Offset bottomRight = tester.getBottomRight(find.byKey(sliderKey));

    final Offset target = topLeft + (bottomRight - topLeft) / 4.0;
    await tester.tapAt(target);
    expect(value, closeTo(0.75, 0.05));
    await tester.pump(); // No animation should start.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });

  testWidgets("Slider doesn't send duplicate change events if tapped on the same value", (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    double startValue;
    double endValue;
    int updates = 0;
    int startValueUpdates = 0;
    int endValueUpdates = 0;


    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      onChanged: (double newValue) {
                        setState(() {
                          updates++;
                          value = newValue;
                        });
                      },
                      onChangeStart: (double value) {
                        startValueUpdates++;
                        startValue = value;
                      },
                      onChangeEnd: (double value) {
                        endValueUpdates++;
                        endValue = value;
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    expect(startValue, equals(0.0));
    expect(endValue, equals(0.5));
    await tester.pump();
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    await tester.pump();
    expect(updates, equals(1));
    expect(startValueUpdates, equals(2));
    expect(endValueUpdates, equals(2));
  });

  testWidgets('Value indicator shows for a bit after being tapped', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      divisions: 4,
                      onChanged: (double newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    await tester.pump(const Duration(milliseconds: 100));
    // Starts with the position animation and value indicator
    expect(SchedulerBinding.instance.transientCallbackCount, equals(2));
    await tester.pump(const Duration(milliseconds: 100));
    // Value indicator is longer than position.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
    await tester.pump(const Duration(milliseconds: 100));
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.pump(const Duration(milliseconds: 100));
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.pump(const Duration(milliseconds: 100));
    // Shown for long enough, value indicator is animated closed.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
    await tester.pump(const Duration(milliseconds: 101));
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });

  testWidgets('Discrete Slider repaints and animates when dragged', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    final List<Offset> log = <Offset>[];
    final LoggingThumbShape loggingThumb = LoggingThumbShape(log);
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              final SliderThemeData sliderTheme = SliderTheme.of(context).copyWith(thumbShape: loggingThumb);
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: SliderTheme(
                      data: sliderTheme,
                      child: Slider(
                        key: sliderKey,
                        value: value,
                        divisions: 4,
                        onChanged: (double newValue) {
                          setState(() {
                            value = newValue;
                          });
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final List<Offset> expectedLog = <Offset>[
      const Offset(24.0, 300.0),
      const Offset(24.0, 300.0),
      const Offset(400.0, 300.0),
    ];
    final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 100));
    expect(value, equals(0.5));
    expect(log.length, 3);
    expect(log, orderedEquals(expectedLog));
    await gesture.moveBy(const Offset(-500.0, 0.0));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 10));
    expect(value, equals(0.0));
    expect(log.length, 5);
    expect(log.last.dx, closeTo(386.6, 0.1));
    // With no more gesture or value changes, the thumb position should still
    // be redrawn in the animated position.
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 10));
    expect(value, equals(0.0));
    expect(log.length, 7);
    expect(log.last.dx, closeTo(344.5, 0.1));
    // Final position.
    await tester.pump(const Duration(milliseconds: 80));
    expectedLog.add(const Offset(24.0, 300.0));
    expect(value, equals(0.0));
    expect(log.length, 8);
    expect(log.last.dx, closeTo(24.0, 0.1));
    await gesture.up();
  });

  testWidgets("Slider doesn't send duplicate change events if tapped on the same value", (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    int updates = 0;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      onChanged: (double newValue) {
                        setState(() {
                          updates++;
                          value = newValue;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    await tester.pump();
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(0.5));
    await tester.pump();
    expect(updates, equals(1));
  });

  testWidgets('discrete Slider repaints when dragged', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    final List<Offset> log = <Offset>[];
    final LoggingThumbShape loggingThumb = LoggingThumbShape(log);
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              final SliderThemeData sliderTheme = SliderTheme.of(context).copyWith(thumbShape: loggingThumb);
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: SliderTheme(
                      data: sliderTheme,
                      child: Slider(
                        key: sliderKey,
                        value: value,
                        divisions: 4,
                        onChanged: (double newValue) {
                          setState(() {
                            value = newValue;
                          });
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final List<Offset> expectedLog = <Offset>[
      const Offset(24.0, 300.0),
      const Offset(24.0, 300.0),
      const Offset(400.0, 300.0),
    ];
    final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 100));
    expect(value, equals(0.5));
    expect(log.length, 3);
    expect(log, orderedEquals(expectedLog));
    await gesture.moveBy(const Offset(-500.0, 0.0));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 10));
    expect(value, equals(0.0));
    expect(log.length, 5);
    expect(log.last.dx, closeTo(386.6, 0.1));
    // With no more gesture or value changes, the thumb position should still
    // be redrawn in the animated position.
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 10));
    expect(value, equals(0.0));
    expect(log.length, 7);
    expect(log.last.dx, closeTo(344.5, 0.1));
    // Final position.
    await tester.pump(const Duration(milliseconds: 80));
    expectedLog.add(const Offset(24.0, 300.0));
    expect(value, equals(0.0));
    expect(log.length, 8);
    expect(log.last.dx, closeTo(24.0, 0.1));
    await gesture.up();
  });

  testWidgets('Slider take on discrete values', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: SizedBox(
                      width: 144.0 + 2 * 16.0, // _kPreferredTotalWidth
                      child: Slider(
                        key: sliderKey,
                        min: 0.0,
                        max: 100.0,
                        divisions: 10,
                        value: value,
                        onChanged: (double newValue) {
                          setState(() {
                            value = newValue;
                          });
                        },
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey));
    expect(value, equals(50.0));
    await tester.drag(find.byKey(sliderKey), const Offset(5.0, 0.0));
    expect(value, equals(50.0));
    await tester.drag(find.byKey(sliderKey), const Offset(40.0, 0.0));
    expect(value, equals(80.0));

    await tester.pump(); // Starts animation.
    expect(SchedulerBinding.instance.transientCallbackCount, greaterThan(0));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    // Animation complete.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });

  testWidgets('Slider can be given zero values', (WidgetTester tester) async {
    final List<double> log = <double>[];
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Slider(
                value: 0.0,
                min: 0.0,
                max: 1.0,
                onChanged: (double newValue) {
                  log.add(newValue);
                },
              ),
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byType(Slider));
    expect(log, <double>[0.5]);
    log.clear();

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Slider(
                value: 0.0,
                min: 0.0,
                max: 0.0,
                onChanged: (double newValue) {
                  log.add(newValue);
                },
              ),
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byType(Slider));
    expect(log, <double>[]);
    log.clear();
  });

  testWidgets('Slider uses the right theme colors for the right components', (WidgetTester tester) async {
    const Color customColor1 = Color(0xcafefeed);
    const Color customColor2 = Color(0xdeadbeef);
    final ThemeData theme = 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),
      ),
    );
    final SliderThemeData sliderTheme = theme.sliderTheme;
    double value = 0.45;
    Widget buildApp({
      Color activeColor,
      Color inactiveColor,
      int divisions,
      bool enabled = true,
    }) {
      final ValueChanged<double> onChanged = !enabled
        ? null
        : (double d) {
            value = d;
          };
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Center(
                child: Theme(
                  data: theme,
                  child: Slider(
                    value: value,
                    label: '$value',
                    divisions: divisions,
                    activeColor: activeColor,
                    inactiveColor: inactiveColor,
                    onChanged: onChanged,
                  ),
                ),
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildApp());

    final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
    final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));

    // Check default theme for enabled widget.
    expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
    expect(material, paints..shadow(color: const Color(0xff000000)));
    expect(material, paints..circle(color: sliderTheme.thumbColor));
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));

    // Test setting only the activeColor.
    await tester.pumpWidget(buildApp(activeColor: customColor1));
    expect(material, paints..rrect(color: customColor1)..rrect(color: sliderTheme.inactiveTrackColor));
    expect(material, paints..shadow(color: Colors.black));
    expect(material, paints..circle(color: customColor1));
    expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));

    // Test setting only the inactiveColor.
    await tester.pumpWidget(buildApp(inactiveColor: customColor1));
    expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: customColor1));
    expect(material, paints..shadow(color: Colors.black));
    expect(material, paints..circle(color: sliderTheme.thumbColor));
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));

    // Test setting both activeColor and inactiveColor.
    await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2));
    expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
    expect(material, paints..shadow(color: Colors.black));
    expect(material, paints..circle(color: customColor1));
    expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));

    // Test colors for discrete slider.
    await tester.pumpWidget(buildApp(divisions: 3));
    expect(material, paints..rrect(color: sliderTheme.activeTrackColor)..rrect(color: sliderTheme.inactiveTrackColor));
    expect(
        material,
        paints
          ..circle(color: sliderTheme.activeTickMarkColor)
          ..circle(color: sliderTheme.activeTickMarkColor)
          ..circle(color: sliderTheme.inactiveTickMarkColor)
          ..circle(color: sliderTheme.inactiveTickMarkColor)
          ..shadow(color: Colors.black)
          ..circle(color: sliderTheme.thumbColor)
    );
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));

    // Test colors for discrete slider with inactiveColor and activeColor set.
    await tester.pumpWidget(buildApp(
      activeColor: customColor1,
      inactiveColor: customColor2,
      divisions: 3,
    ));
    expect(material, paints..rrect(color: customColor1)..rrect(color: customColor2));
    expect(
        material,
        paints
          ..circle(color: customColor2)
          ..circle(color: customColor2)
          ..circle(color: customColor1)
          ..circle(color: customColor1)
          ..shadow(color: Colors.black)
          ..circle(color: customColor1));
    expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.disabledThumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledActiveTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.disabledInactiveTrackColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.activeTickMarkColor)));
    expect(material, isNot(paints..circle(color: sliderTheme.inactiveTickMarkColor)));

    // Test default theme for disabled widget.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
        material,
        paints
          ..rrect(color: sliderTheme.disabledActiveTrackColor)
          ..rrect(color: sliderTheme.disabledInactiveTrackColor));
    expect(material, paints..shadow(color: Colors.black)..circle(color: sliderTheme.disabledThumbColor));
    expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));

    // Test setting the activeColor and inactiveColor for disabled widget.
    await tester.pumpWidget(buildApp(activeColor: customColor1, inactiveColor: customColor2, enabled: false));
    expect(
        material,
        paints
          ..rrect(color: sliderTheme.disabledActiveTrackColor)
          ..rrect(color: sliderTheme.disabledInactiveTrackColor));
    expect(material, paints..circle(color: sliderTheme.disabledThumbColor));
    expect(material, isNot(paints..circle(color: sliderTheme.thumbColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.activeTrackColor)));
    expect(material, isNot(paints..rrect(color: sliderTheme.inactiveTrackColor)));

    // Test that the default value indicator has the right colors.
    await tester.pumpWidget(buildApp(divisions: 3));
    Offset center = tester.getCenter(find.byType(Slider));
    TestGesture gesture = await tester.startGesture(center);
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();
    expect(value, equals(2.0 / 3.0));
    expect(
      valueIndicatorBox,
      paints
        ..path(color: sliderTheme.valueIndicatorColor)
        ..paragraph(),
    );
    await gesture.up();
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();

    // Testing the custom colors are used for the indicator.
    await tester.pumpWidget(buildApp(
      divisions: 3,
      activeColor: customColor1,
      inactiveColor: customColor2,
    ));
    center = tester.getCenter(find.byType(Slider));
    gesture = await tester.startGesture(center);
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();
    expect(value, equals(2.0 / 3.0));
    expect(
      valueIndicatorBox,
      paints
        ..rrect(color: customColor1) // active track
        ..rrect(color: customColor2) // inactive track
        ..circle(color: customColor1.withOpacity(0.12)) // overlay
        ..circle(color: customColor2) // 1st tick mark
        ..circle(color: customColor2) // 2nd tick mark
        ..circle(color: customColor2) // 3rd tick mark
        ..circle(color: customColor1) // 4th tick mark
        ..shadow(color: Colors.black)
        ..circle(color: customColor1) // thumb
        ..path(color: sliderTheme.valueIndicatorColor), // indicator
    );
    await gesture.up();
  });

  testWidgets('Slider can tap in vertical scroller', (WidgetTester tester) async {
    double value = 0.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: ListView(
                children: <Widget>[
                  Slider(
                    value: value,
                    onChanged: (double newValue) {
                      value = newValue;
                    },
                  ),
                  Container(
                    height: 2000.0,
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.byType(Slider));
    expect(value, equals(0.5));
  });

  testWidgets('Slider drags immediately (LTR)', (WidgetTester tester) async {
    double value = 0.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Center(
                child: Slider(
                  value: value,
                  onChanged: (double newValue) {
                    value = newValue;
                  },
                ),
              ),
            ),
          ),
        ),
      ),
    );

    final Offset center = tester.getCenter(find.byType(Slider));
    final TestGesture gesture = await tester.startGesture(center);

    expect(value, equals(0.5));

    await gesture.moveBy(const Offset(1.0, 0.0));

    expect(value, greaterThan(0.5));

    await gesture.up();
  });

  testWidgets('Slider drags immediately (RTL)', (WidgetTester tester) async {
    double value = 0.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Center(
                child: Slider(
                  value: value,
                  onChanged: (double newValue) {
                    value = newValue;
                  },
                ),
              ),
            ),
          ),
        ),
      ),
    );

    final Offset center = tester.getCenter(find.byType(Slider));
    final TestGesture gesture = await tester.startGesture(center);

    expect(value, equals(0.5));

    await gesture.moveBy(const Offset(1.0, 0.0));

    expect(value, lessThan(0.5));

    await gesture.up();
  });

  testWidgets('Slider sizing', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: const Material(
              child: Center(
                child: Slider(
                  value: 0.5,
                  onChanged: null,
                ),
              ),
            ),
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(800.0, 600.0));

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: const Material(
              child: Center(
                child: IntrinsicWidth(
                  child: Slider(
                    value: 0.5,
                    onChanged: null,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 24.0, 600.0));

    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: const Material(
              child: Center(
                child: OverflowBox(
                  maxWidth: double.infinity,
                  maxHeight: double.infinity,
                  child: Slider(
                    value: 0.5,
                    onChanged: null,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Slider)).size, const Size(144.0 + 2.0 * 24.0, 48.0));
  });

  testWidgets('Slider respects textScaleFactor', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    Widget buildSlider({
      double textScaleFactor,
      bool isDiscrete = true,
      ShowValueIndicator show = ShowValueIndicator.onlyForDiscrete,
    }) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData(textScaleFactor: textScaleFactor),
                child: Material(
                  child: Theme(
                    data: Theme.of(context).copyWith(
                      sliderTheme: Theme.of(context).sliderTheme.copyWith(showValueIndicator: show),
                    ),
                    child: Center(
                      child: OverflowBox(
                        maxWidth: double.infinity,
                        maxHeight: double.infinity,
                        child: Slider(
                          key: sliderKey,
                          min: 0.0,
                          max: 100.0,
                          divisions: isDiscrete ? 10 : null,
                          label: '${value.round()}',
                          value: value,
                          onChanged: (double newValue) {
                            setState(() {
                              value = newValue;
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildSlider(textScaleFactor: 1.0));
    Offset center = tester.getCenter(find.byType(Slider));
    TestGesture gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    expect(
      tester.renderObject(find.byType(Overlay)),
      paints
        ..path(
          includes: const <Offset>[
            Offset(0.0, 0.0),
            Offset(0.0, -8.0),
            Offset(-276.0, -16.0),
            Offset(-216.0, -16.0),
          ],
          color: const Color(0xf55f5f5f),
        )
        ..paragraph(),
    );

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

    await tester.pumpWidget(buildSlider(textScaleFactor: 2.0));
    center = tester.getCenter(find.byType(Slider));
    gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    expect(
      tester.renderObject(find.byType(Overlay)),
      paints
        ..path(
          includes: const <Offset>[
            Offset(0.0, 0.0),
            Offset(0.0, -8.0),
            Offset(-304.0, -16.0),
            Offset(-216.0, -16.0),
          ],
          color: const Color(0xf55f5f5f),
        )
        ..paragraph(),
    );

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

    // Check continuous
    await tester.pumpWidget(buildSlider(
      textScaleFactor: 1.0,
      isDiscrete: false,
      show: ShowValueIndicator.onlyForContinuous,
    ));
    center = tester.getCenter(find.byType(Slider));
    gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    expect(tester.renderObject(find.byType(Overlay)),
      paints
        ..path(
          includes: const <Offset>[
            Offset(0.0, 0.0),
            Offset(0.0, -8.0),
            Offset(-276.0, -16.0),
            Offset(-216.0, -16.0),
          ],
          color: const Color(0xf55f5f5f),
        )
        ..paragraph(),
    );

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

    await tester.pumpWidget(buildSlider(
      textScaleFactor: 2.0,
      isDiscrete: false,
      show: ShowValueIndicator.onlyForContinuous,
    ));
    center = tester.getCenter(find.byType(Slider));
    gesture = await tester.startGesture(center);
    await tester.pumpAndSettle();

    expect(
      tester.renderObject(find.byType(Overlay)),
      paints
        ..path(
          includes: const <Offset>[
            Offset(0.0, 0.0),
            Offset(0.0, -8.0),
            Offset(-276.0, -16.0),
            Offset(-216.0, -16.0),
          ],
          color: const Color(0xf55f5f5f),
        )
        ..paragraph(),
    );

    await gesture.up();
    await tester.pumpAndSettle();
  }, skip: isBrowser);

  testWidgets('Tick marks are skipped when they are too dense', (WidgetTester tester) async {
    Widget buildSlider({
      int divisions,
    }) {
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Center(
                child: Slider(
                  min: 0.0,
                  max: 100.0,
                  divisions: divisions,
                  value: 0.25,
                  onChanged: (double newValue) { },
                ),
              ),
            ),
          ),
        ),
      );
    }

    // Pump a slider with a reasonable amount of divisions to verify that the
    // tick marks are drawn when the number of tick marks is not too dense.
    await tester.pumpWidget(
      buildSlider(
        divisions: 4,
      ),
    );

    final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));

    // 5 tick marks and a thumb.
    expect(material, paintsExactlyCountTimes(#drawCircle, 6));

    // 200 divisions will produce a tick interval off less than 6,
    // which would be too dense to draw.
    await tester.pumpWidget(
      buildSlider(
        divisions: 200,
      ),
    );

    // No tick marks are drawn because they are too dense, but the thumb is
    // still drawn.
    expect(material, paintsExactlyCountTimes(#drawCircle, 1));
  });

  testWidgets('Slider has correct animations when reparented', (WidgetTester tester) async {
    final Key sliderKey = GlobalKey(debugLabel: 'A');
    double value = 0.0;

    Widget buildSlider(int parents) {
      Widget createParents(int parents, StateSetter setState) {
        Widget slider = Slider(
          key: sliderKey,
          value: value,
          divisions: 4,
          onChanged: (double newValue) {
            setState(() {
              value = newValue;
            });
          },
        );

        for (int i = 0; i < parents; ++i) {
          slider = Column(children: <Widget>[slider]);
        }
        return slider;
      }

      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: createParents(parents, setState),
                ),
              );
            },
          ),
        ),
      );
    }

    Future<void> testReparenting(bool reparent) async {
      final MaterialInkController material = Material.of(tester.element(find.byType(Slider)));
      final Offset center = tester.getCenter(find.byType(Slider));
      // Move to 0.0.
      TestGesture gesture = await tester.startGesture(Offset.zero);
      await tester.pump();
      await gesture.up();
      await tester.pumpAndSettle();
      expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
      expect(
        material,
        paints
          ..circle(x: 26.0, y: 24.0, radius: 1.0)
          ..circle(x: 213.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 1.0)
          ..circle(x: 587.0, y: 24.0, radius: 1.0)
          ..circle(x: 774.0, y: 24.0, radius: 1.0)
          ..circle(x: 24.0, y: 24.0, radius: 10.0),
      );

      gesture = await tester.startGesture(center);
      await tester.pump();
      // Wait for animations to start.
      await tester.pump(const Duration(milliseconds: 25));
      expect(SchedulerBinding.instance.transientCallbackCount, equals(2));
      expect(
        material,
        paints
          ..circle(x: 111.20703125, y: 24.0, radius: 5.687664985656738)
          ..circle(x: 26.0, y: 24.0, radius: 1.0)
          ..circle(x: 213.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 1.0)
          ..circle(x: 587.0, y: 24.0, radius: 1.0)
          ..circle(x: 774.0, y: 24.0, radius: 1.0)
          ..circle(x: 111.20703125, y: 24.0, radius: 10.0),
      );

      // Reparenting in the middle of an animation should do nothing.
      if (reparent) {
        await tester.pumpWidget(buildSlider(2));
      }

      // Move a little further in the animations.
      await tester.pump(const Duration(milliseconds: 10));
      expect(SchedulerBinding.instance.transientCallbackCount, equals(2));
      expect(
        material,
        paints
          ..circle(x: 190.0135726928711, y: 24.0, radius: 12.0)
          ..circle(x: 26.0, y: 24.0, radius: 1.0)
          ..circle(x: 213.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 1.0)
          ..circle(x: 587.0, y: 24.0, radius: 1.0)
          ..circle(x: 774.0, y: 24.0, radius: 1.0)
          ..circle(x: 190.0135726928711, y: 24.0, radius: 10.0),
      );
      // Wait for animations to finish.
      await tester.pumpAndSettle();
      expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
      expect(
        material,
        paints
          ..circle(x: 400.0, y: 24.0, radius: 24.0)
          ..circle(x: 26.0, y: 24.0, radius: 1.0)
          ..circle(x: 213.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 1.0)
          ..circle(x: 587.0, y: 24.0, radius: 1.0)
          ..circle(x: 774.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 10.0),
      );
      await gesture.up();
      await tester.pumpAndSettle();
      expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
      expect(
        material,
        paints
          ..circle(x: 26.0, y: 24.0, radius: 1.0)
          ..circle(x: 213.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 1.0)
          ..circle(x: 587.0, y: 24.0, radius: 1.0)
          ..circle(x: 774.0, y: 24.0, radius: 1.0)
          ..circle(x: 400.0, y: 24.0, radius: 10.0),
      );
    }

    await tester.pumpWidget(buildSlider(1));
    // Do it once without reparenting in the middle of an animation
    await testReparenting(false);
    // Now do it again with reparenting in the middle of an animation.
    await testReparenting(true);
  });


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

    await tester.pumpWidget(MaterialApp(
      home: Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: MediaQueryData.fromWindow(window),
          child: Material(
            child: Slider(
              value: 0.5,
              onChanged: (double v) { },
            ),
          ),
        ),
      ),
    ));

    await tester.pumpAndSettle();

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics(
              id: 1,
              textDirection: TextDirection.ltr,
              children: <TestSemantics>[
                TestSemantics(
                  id: 2,
                  children: <TestSemantics>[
                    TestSemantics(
                      id: 3,
                      flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                      children: <TestSemantics>[
                        TestSemantics(
                          id: 4,
                          flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable],
                          actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
                          value: '50%',
                          increasedValue: '55%',
                          decreasedValue: '45%',
                          textDirection: TextDirection.ltr,
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    // Disable slider
    await tester.pumpWidget(MaterialApp(
      home: Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: MediaQueryData.fromWindow(window),
          child: const Material(
            child: Slider(
              value: 0.5,
              onChanged: null,
            ),
          ),
        ),
      ),
    ));

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics(
              id: 1,
              textDirection: TextDirection.ltr,
              children: <TestSemantics>[
                TestSemantics(
                  id: 2,
                  children: <TestSemantics>[
                    TestSemantics(
                      id: 3,
                      flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                      children: <TestSemantics>[
                        TestSemantics(
                          id: 4,
                          flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState],
                          value: '50%',
                          increasedValue: '55%',
                          decreasedValue: '45%',
                          textDirection: TextDirection.ltr,
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );
    semantics.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));

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

    await tester.pumpWidget(
        MaterialApp(
          home: Theme(
            data: ThemeData.light(),
            child: Directionality(
              textDirection: TextDirection.ltr,
              child: MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Slider(
                    value: 100.0,
                    min: 0.0,
                    max: 200.0,
                    onChanged: (double v) { },
                  ),
                ),
              ),
            ),
          ),
        )
    );

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics(
              id: 1,
              textDirection: TextDirection.ltr,
              children: <TestSemantics>[
                TestSemantics(
                  id: 2,
                  children: <TestSemantics>[
                    TestSemantics(
                      id: 3,
                      flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                      children: <TestSemantics>[
                        TestSemantics(
                          id: 4,
                          flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable],
                          actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
                          value: '50%',
                          increasedValue: '60%',
                          decreasedValue: '40%',
                          textDirection: TextDirection.ltr,
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );

    // Disable slider
    await tester.pumpWidget(MaterialApp(
      home: Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: MediaQueryData.fromWindow(window),
          child: const Material(
            child: Slider(
              value: 0.5,
              onChanged: null,
            ),
          ),
        ),
      ),
    ));

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics(
              id: 1,
              textDirection: TextDirection.ltr,
              children: <TestSemantics>[
                TestSemantics(
                  id: 2,
                  children: <TestSemantics>[
                    TestSemantics(
                      id: 3,
                      flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                      children: <TestSemantics>[
                        TestSemantics(
                          id: 5,
                          flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState],
                          value: '50%',
                          increasedValue: '60%',
                          decreasedValue: '40%',
                          textDirection: TextDirection.ltr,
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );
    semantics.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('Slider semantics with custom formatter', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(MaterialApp(
      home: Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: MediaQueryData.fromWindow(window),
          child: Material(
            child: Slider(
              value: 40.0,
              min: 0.0,
              max: 200.0,
              divisions: 10,
              semanticFormatterCallback: (double value) => value.round().toString(),
              onChanged: (double v) { },
            ),
          ),
        ),
      ),
    ));

    expect(
      semantics,
      hasSemantics(
        TestSemantics.root(
          children: <TestSemantics>[
            TestSemantics(
              id: 1,
              textDirection: TextDirection.ltr,
              children: <TestSemantics>[
                TestSemantics(
                  id: 2,
                  children: <TestSemantics>[
                    TestSemantics(
                      id: 3,
                      flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                      children: <TestSemantics>[
                        TestSemantics(
                          id: 4,
                          flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable],
                          actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
                          value: '40',
                          increasedValue: '60',
                          decreasedValue: '20',
                          textDirection: TextDirection.ltr,
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
        ignoreRect: true,
        ignoreTransform: true,
      ),
    );
    semantics.dispose();
  });

  testWidgets('Slider is focusable and has correct focus color', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode(debugLabel: 'Slider');
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return SliderTheme(
                data: SliderThemeData(
                  overlayColor: Colors.orange[500],
                ),
                child: Slider(
                  value: value,
                  onChanged: enabled ? (double newValue) {
                    setState(() {
                      value = newValue;
                    });
                  } : null,
                  autofocus: true,
                  focusNode: focusNode,
                ),
              );
            }),
          ),
        ),
      );
    }
    await tester.pumpWidget(buildApp());

    // Check that the overlay shows when focused.
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isTrue);
    expect(
      Material.of(tester.element(find.byType(Slider))),
      paints..circle(color: Colors.orange[500]),
    );

    // Check that the overlay does not show when focused and disabled.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(focusNode.hasPrimaryFocus, isFalse);
    expect(
      Material.of(tester.element(find.byType(Slider))),
      isNot(paints..circle(color: Colors.orange[500])),
    );
  });

  testWidgets('Slider can be hovered and has correct hover color', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    Widget buildApp({bool enabled = true}) {
      return MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return SliderTheme(
                data: SliderThemeData(
                  overlayColor: Colors.orange[500],
                ),
                child: Slider(
                  value: value,
                  onChanged: enabled ? (double newValue) {
                    setState(() {
                      value = newValue;
                    });
                  } : null,
                ),
              );
            }),
          ),
        ),
      );
    }
    await tester.pumpWidget(buildApp());

    // Slider does not have overlay when enabled and not hovered.
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Slider))),
      isNot(paints..circle(color: Colors.orange[500])),
    );

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

    // Slider has overlay when enabled and hovering.
    await tester.pumpWidget(buildApp());
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Slider))),
      paints..circle(color: Colors.orange[500]),
    );

    // Slider does not have an overlay when disabled and hovering.
    await tester.pumpWidget(buildApp(enabled: false));
    await tester.pumpAndSettle();
    expect(
      Material.of(tester.element(find.byType(Slider))),
      isNot(paints..circle(color: Colors.orange[500])),
    );
  });

  testWidgets('Slider can be incremented and decremented by keyboard shortcuts - LTR', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return Slider(
                value: value,
                onChanged: (double newValue) {
                  setState(() {
                    value = newValue;
                  });
                },
                autofocus: true,
              );
            }),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
    await tester.pumpAndSettle();
    expect(value, 0.55);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
    await tester.pumpAndSettle();
    expect(value, 0.5);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pumpAndSettle();
    expect(value, 0.55);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pumpAndSettle();
    expect(value, 0.5);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));

  testWidgets('Slider can be incremented and decremented by keyboard shortcuts - LTR', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return Slider(
                value: value,
                onChanged: (double newValue) {
                  setState(() {
                    value = newValue;
                  });
                },
                autofocus: true,
              );
            }),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
    await tester.pumpAndSettle();
    expect(value, 0.6);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
    await tester.pumpAndSettle();
    expect(value, 0.5);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pumpAndSettle();
    expect(value, 0.6);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pumpAndSettle();
    expect(value, 0.5);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('Slider can be incremented and decremented by keyboard shortcuts - RTL', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return Directionality(
                textDirection: TextDirection.rtl,
                child: Slider(
                  value: value,
                  onChanged: (double newValue) {
                    setState(() {
                      value = newValue;
                    });
                  },
                  autofocus: true,
                ),
              );
            }),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
    await tester.pumpAndSettle();
    expect(value, 0.45);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
    await tester.pumpAndSettle();
    expect(value, 0.5);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pumpAndSettle();
    expect(value, 0.55);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pumpAndSettle();
    expect(value, 0.5);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));

  testWidgets('Slider can be incremented and decremented by keyboard shortcuts - RTL', (WidgetTester tester) async {
    tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
    double value = 0.5;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
              return Directionality(
                textDirection: TextDirection.rtl,
                child: Slider(
                  value: value,
                  onChanged: (double newValue) {
                    setState(() {
                      value = newValue;
                    });
                  },
                  autofocus: true,
                ),
              );
            }),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
    await tester.pumpAndSettle();
    expect(value, 0.4);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
    await tester.pumpAndSettle();
    expect(value, 0.5);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pumpAndSettle();
    expect(value, 0.6);

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pumpAndSettle();
    expect(value, 0.5);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('Value indicator appears when it should', (WidgetTester tester) async {
    final ThemeData baseTheme = ThemeData(
      platform: TargetPlatform.android,
      primarySwatch: Colors.blue,
    );
    SliderThemeData theme = baseTheme.sliderTheme;
    double value = 0.45;
    Widget buildApp({ SliderThemeData sliderTheme, int divisions, bool enabled = true }) {
      final ValueChanged<double> onChanged = enabled ? (double d) => value = d : null;
      return MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData.fromWindow(window),
            child: Material(
              child: Center(
                child: Theme(
                  data: baseTheme,
                  child: SliderTheme(
                    data: sliderTheme,
                    child: Slider(
                      value: value,
                      label: '$value',
                      divisions: divisions,
                      onChanged: onChanged,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      );
    }

    Future<void> expectValueIndicator({
      bool isVisible,
      SliderThemeData theme,
      int divisions,
      bool enabled = true,
    }) async {
      // Discrete enabled widget.
      await tester.pumpWidget(buildApp(sliderTheme: theme, divisions: divisions, enabled: enabled));
      final Offset center = tester.getCenter(find.byType(Slider));
      final TestGesture gesture = await tester.startGesture(center);
      // Wait for value indicator animation to finish.
      await tester.pumpAndSettle();


      final RenderBox valueIndicatorBox = tester.renderObject(find.byType(Overlay));
      expect(
        valueIndicatorBox,
        isVisible
            ? (paints..path(color: theme.valueIndicatorColor)..paragraph())
            : isNot(paints..path(color: theme.valueIndicatorColor)..paragraph()),
      );
      await gesture.up();
    }

    // Default (showValueIndicator set to onlyForDiscrete).
    await expectValueIndicator(isVisible: true, theme: theme, divisions: 3, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: false);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: false);

    // With showValueIndicator set to onlyForContinuous.
    theme = theme.copyWith(showValueIndicator: ShowValueIndicator.onlyForContinuous);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: false);
    await expectValueIndicator(isVisible: true, theme: theme, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: false);

    // discrete enabled widget with showValueIndicator set to always.
    theme = theme.copyWith(showValueIndicator: ShowValueIndicator.always);
    await expectValueIndicator(isVisible: true, theme: theme, divisions: 3, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: false);
    await expectValueIndicator(isVisible: true, theme: theme, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: false);

    // discrete enabled widget with showValueIndicator set to never.
    theme = theme.copyWith(showValueIndicator: ShowValueIndicator.never);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, divisions: 3, enabled: false);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: true);
    await expectValueIndicator(isVisible: false, theme: theme, enabled: false);
  });

  testWidgets("Slider doesn't start any animations after dispose", (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: Slider(
                      key: sliderKey,
                      value: value,
                      divisions: 4,
                      onChanged: (double newValue) {
                        setState(() {
                          value = newValue;
                        });
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(sliderKey)));
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
    expect(value, equals(0.5));
    await gesture.moveBy(const Offset(-500.0, 0.0));
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
    // Change the tree to dispose the original widget.
    await tester.pumpWidget(Container());
    expect(await tester.pumpAndSettle(const Duration(milliseconds: 100)), equals(1));
    await gesture.up();
  });

  testWidgets('Slider removes value indicator from overlay if Slider gets disposed without value indicator animation completing.', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    const Color fillColor = Color(0xf55f5f5f);
    double value = 0.0;

    Widget buildApp({
      Color activeColor,
      Color inactiveColor,
      int divisions,
      bool enabled = true,
    }) {
      return MaterialApp(
        home: Scaffold(
          body: Builder(
            // 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.
            builder: (BuildContext context) {
              return Column(
                children: <Widget>[
                  Slider(
                    key: sliderKey,
                    min: 0.0,
                    max: 100.0,
                    divisions: divisions,
                    label: '${value.round()}',
                    value: value,
                    onChanged: (double newValue) {
                      value = newValue;
                    },
                  ),
                  RaisedButton(
                    child: const Text('Next'),
                    onPressed: () {
                      Navigator.of(context).pushReplacement(
                        MaterialPageRoute<void>(
                          builder: (BuildContext context) {
                            return RaisedButton(
                              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(Slider)).translate(-24, 0);
    final TestGesture gesture = await tester.startGesture(topRight);
    // Wait for value indicator animation to finish.
    await tester.pumpAndSettle();

    expect(find.byType(Slider), isNotNull);
    expect(
      valueIndicatorBox,
      paints
        // Represents the raised button with text, next.
        ..path(color: Colors.black)
        ..paragraph()
        // Represents the Slider.
        ..path(color: fillColor)
        ..paragraph()
    );

    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 2));
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 2));

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

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

    // Represents the RaisedButton with inner Text, inner page.
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawPath, 1));
    expect(valueIndicatorBox, paintsExactlyCountTimes(#drawParagraph, 1));

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

  testWidgets('Slider.adaptive', (WidgetTester tester) async {
    double value = 0.5;

    Widget buildFrame(TargetPlatform platform) {
      return MaterialApp(
        theme: ThemeData(platform: platform),
        home: StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return Material(
              child: Center(
                child: Slider.adaptive(
                  value: value,
                  onChanged: (double newValue) {
                    setState(() {
                      value = newValue;
                    });
                  },
                ),
              ),
            );
          },
        ),
      );
    }

    for (final TargetPlatform platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
      value = 0.5;
      await tester.pumpWidget(buildFrame(platform));
      expect(find.byType(Slider), findsOneWidget);
      expect(find.byType(CupertinoSlider), findsOneWidget);

      expect(value, 0.5, reason: 'on ${describeEnum(platform)}');
      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CupertinoSlider)));
      // Drag to the right end of the track.
      await gesture.moveBy(const Offset(600.0, 0.0));
      expect(value, 1.0, reason: 'on ${describeEnum(platform)}');
      await gesture.up();
    }

    for (final TargetPlatform platform in <TargetPlatform>[TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows]) {
      value = 0.5;
      await tester.pumpWidget(buildFrame(platform));
      await tester.pumpAndSettle(); // Finish the theme change animation.
      expect(find.byType(Slider), findsOneWidget);
      expect(find.byType(CupertinoSlider), findsNothing);

      expect(value, 0.5, reason: 'on ${describeEnum(platform)}');
      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Slider)));
      // Drag to the right end of the track.
      await gesture.moveBy(const Offset(600.0, 0.0));
      expect(value, 1.0, reason: 'on ${describeEnum(platform)}');
      await gesture.up();
    }
  });

  testWidgets('Slider respects height from theme', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              final SliderThemeData sliderTheme = SliderTheme.of(context).copyWith(tickMarkShape: TallSliderTickMarkShape());
              return MediaQuery(
                data: MediaQueryData.fromWindow(window),
                child: Material(
                  child: Center(
                    child: IntrinsicHeight(
                      child: SliderTheme(
                        data: sliderTheme,
                        child: Slider(
                          key: sliderKey,
                          value: value,
                          divisions: 4,
                          onChanged: (double newValue) {
                            setState(() {
                              value = newValue;
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    final RenderBox renderObject = tester.renderObject<RenderBox>(find.byType(Slider));
    expect(renderObject.size.height, 200);
  });

  testWidgets('Slider changes mouse cursor when hovered', (WidgetTester tester) async {
    // Test Slider() constructor
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Slider(
                  mouseCursor: SystemMouseCursors.text,
                  value: 0.5,
                  onChanged: (double newValue) { },
                ),
              ),
            ),
          ),
        ),
      )
    );

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

    await tester.pump();

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

    // Test Slider.adaptive() constructor
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Slider.adaptive(
                  mouseCursor: SystemMouseCursors.text,
                  value: 0.5,
                  onChanged: (double newValue) { },
                ),
              ),
            ),
          ),
        ),
      )
    );

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

    // Test default cursor
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: Material(
            child: Center(
              child: MouseRegion(
                cursor: SystemMouseCursors.forbidden,
                child: Slider(
                  value: 0.5,
                  onChanged: (double newValue) { },
                ),
              ),
            ),
          ),
        ),
      )
    );

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

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

    const Slider(
      activeColor: Colors.blue,
      divisions: 10,
      inactiveColor: Colors.grey,
      label: 'Set a value',
      max: 100.0,
      min: 0.0,
      onChanged: null,
      onChangeEnd: null,
      onChangeStart: null,
      semanticFormatterCallback: null,
      value: 50.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>[
      'value: 50.0',
      'disabled',
      'min: 0.0',
      'max: 100.0',
      'divisions: 10',
      'label: "Set a value"',
      'activeColor: MaterialColor(primary value: Color(0xff2196f3))',
      'inactiveColor: MaterialColor(primary value: Color(0xff9e9e9e))',
    ]);
  });
}
