// 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/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import '../rendering/sliver_utils.dart';


const double VIEWPORT_HEIGHT = 600;
const double VIEWPORT_WIDTH = 300;

void main() {
  testWidgets('SliverCrossAxisGroup is laid out properly', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item')),
        _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item')),
      ]),
    );
    await tester.pumpAndSettle();

    expect(controller.offset, 0);

    expect(find.text('Group 0 Tile 0'), findsOneWidget);
    expect(find.text('Group 0 Tile 1'), findsOneWidget);
    expect(find.text('Group 0 Tile 2'), findsNothing);

    expect(find.text('Group 1 Tile 0'), findsOneWidget);
    expect(find.text('Group 1 Tile 2'), findsOneWidget);
    expect(find.text('Group 1 Tile 3'), findsNothing);

    const double scrollOffset = 18 * 300.0;
    controller.jumpTo(scrollOffset);
    await tester.pumpAndSettle();

    expect(controller.offset, scrollOffset);
    expect(find.text('Group 0 Tile 17'), findsNothing);
    expect(find.text('Group 0 Tile 18'), findsOneWidget);
    expect(find.text('Group 0 Tile 19'), findsOneWidget);
    expect(find.text('Group 1 Tile 19'), findsNothing);

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];

    expect(first.constraints.crossAxisExtent, equals(VIEWPORT_WIDTH / 2));
    expect(second.constraints.crossAxisExtent, equals(VIEWPORT_WIDTH / 2));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(VIEWPORT_WIDTH / 2));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('SliverExpanded is laid out properly', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverCrossAxisExpanded(
          flex: 3,
          sliver: _buildSliverList(
            itemMainAxisExtent: 300,
            items: items,
            label: (int item) => Text('Group 0 Tile $item')
          ),
        ),
        SliverCrossAxisExpanded(
          flex: 2,
          sliver: _buildSliverList(
            itemMainAxisExtent: 200,
            items: items,
            label: (int item) => Text('Group 1 Tile $item')
          ),
        ),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];

    expect(first.constraints.crossAxisExtent, equals(3 * VIEWPORT_WIDTH / 5));
    expect(second.constraints.crossAxisExtent, equals(2 * VIEWPORT_WIDTH / 5));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(3 * VIEWPORT_WIDTH / 5));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('SliverConstrainedCrossAxis is laid out properly', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverConstrainedCrossAxis(maxExtent: 60, sliver: _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item'))),
        SliverConstrainedCrossAxis(maxExtent: 120, sliver: _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item'))),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];

    expect(first.constraints.crossAxisExtent, equals(60));
    expect(second.constraints.crossAxisExtent, equals(120));

    // Check that their parent SliverConstrainedCrossAxis have the correct paintOffsets.
    final List<RenderSliverConstrainedCrossAxis> renderSliversConstrained = tester.renderObjectList<RenderSliverConstrainedCrossAxis>(find.byType(SliverConstrainedCrossAxis)).toList();
    final RenderSliverConstrainedCrossAxis firstConstrained = renderSliversConstrained[0];
    final RenderSliverConstrainedCrossAxis secondConstrained = renderSliversConstrained[1];

    expect((firstConstrained.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    expect((secondConstrained.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(60));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Mix of slivers is laid out properly', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverConstrainedCrossAxis(maxExtent: 30, sliver: _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item'))),
        SliverCrossAxisExpanded(flex: 2, sliver: _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item'))),
        _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 2 Tile $item')),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];
    final RenderSliverList third = renderSlivers[2];

    expect(first.constraints.crossAxisExtent, equals(30));
    expect(second.constraints.crossAxisExtent, equals(180));
    expect(third.constraints.crossAxisExtent, equals(90));

    // Check that paint offset for sliver children are correct as well.
    final RenderSliverCrossAxisGroup sliverCrossAxisRenderObject = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    RenderSliver child = sliverCrossAxisRenderObject.firstChild!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(30));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(210));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Mix of slivers is laid out properly when horizontal', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      scrollDirection: Axis.horizontal,
      slivers: <Widget>[
        SliverConstrainedCrossAxis(
          maxExtent: 30,
          sliver: _buildSliverList(
            scrollDirection: Axis.horizontal,
            itemMainAxisExtent: 300,
            items: items,
            label: (int item) => Text('Group 0 Tile $item')
            )
          ),
        SliverCrossAxisExpanded(
          flex: 2,
          sliver: _buildSliverList(
            scrollDirection: Axis.horizontal,
            itemMainAxisExtent: 200,
            items: items,
            label: (int item) => Text('Group 1 Tile $item')
          )
        ),
        _buildSliverList(
          scrollDirection: Axis.horizontal,
          itemMainAxisExtent: 200,
          items: items,
          label: (int item) => Text('Group 2 Tile $item')
        ),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];
    final RenderSliverList third = renderSlivers[2];

    expect(first.constraints.crossAxisExtent, equals(30));
    expect(second.constraints.crossAxisExtent, equals(380));
    expect(third.constraints.crossAxisExtent, equals(190));

    // Check that paint offset for sliver children are correct as well.
    final RenderSliverCrossAxisGroup sliverCrossAxisRenderObject = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    RenderSliver child = sliverCrossAxisRenderObject.firstChild!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(30));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(410));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Mix of slivers is laid out properly when reversed horizontal', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      scrollDirection: Axis.horizontal,
      reverse: true,
      slivers: <Widget>[
        SliverConstrainedCrossAxis(
          maxExtent: 30,
          sliver: _buildSliverList(
            scrollDirection: Axis.horizontal,
            itemMainAxisExtent: 300,
            items: items,
            label: (int item) => Text('Group 0 Tile $item')
            )
          ),
        SliverCrossAxisExpanded(
          flex: 2,
          sliver: _buildSliverList(
            scrollDirection: Axis.horizontal,
            itemMainAxisExtent: 200,
            items: items,
            label: (int item) => Text('Group 1 Tile $item')
          )
        ),
        _buildSliverList(
          scrollDirection: Axis.horizontal,
          itemMainAxisExtent: 200,
          items: items,
          label: (int item) => Text('Group 2 Tile $item')
        ),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];
    final RenderSliverList third = renderSlivers[2];

    expect(first.constraints.crossAxisExtent, equals(30));
    expect(second.constraints.crossAxisExtent, equals(380));
    expect(third.constraints.crossAxisExtent, equals(190));

    // Check that paint offset for sliver children are correct as well.
    final RenderSliverCrossAxisGroup sliverCrossAxisRenderObject = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    RenderSliver child = sliverCrossAxisRenderObject.firstChild!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(30));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(410));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Mix of slivers is laid out properly when reversed vertical', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      reverse: true,
      slivers: <Widget>[
        SliverConstrainedCrossAxis(
          maxExtent: 30,
          sliver: _buildSliverList(
            itemMainAxisExtent: 300,
            items: items,
            label: (int item) => Text('Group 0 Tile $item')
            )
          ),
        SliverCrossAxisExpanded(
          flex: 2,
          sliver: _buildSliverList(
            itemMainAxisExtent: 200,
            items: items,
            label: (int item) => Text('Group 1 Tile $item')
          )
        ),
        _buildSliverList(
          itemMainAxisExtent: 200,
          items: items,
          label: (int item) => Text('Group 2 Tile $item')
        ),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];
    final RenderSliverList third = renderSlivers[2];

    expect(first.constraints.crossAxisExtent, equals(30));
    expect(second.constraints.crossAxisExtent, equals(180));
    expect(third.constraints.crossAxisExtent, equals(90));

    // Check that paint offset for sliver children are correct as well.
    final RenderSliverCrossAxisGroup sliverCrossAxisRenderObject = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    RenderSliver child = sliverCrossAxisRenderObject.firstChild!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(30));
    child = sliverCrossAxisRenderObject.childAfter(child)!;
    expect((child.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(210));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Assertion error when SliverExpanded is used outside of SliverCrossAxisGroup',
  experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
  (WidgetTester tester) async {
    final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: CustomScrollView(
            slivers: <Widget>[
              SliverCrossAxisExpanded(
                flex: 2,
                sliver: SliverToBoxAdapter(
                  child: Text('Hello World'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
    FlutterError.onError = oldHandler;
    expect(errors, isNotEmpty);
    final AssertionError error = errors.first.exception as AssertionError;
    expect(
      error.toString(),
      contains('renderObject.parent is RenderSliverCrossAxisGroup'),
    );
  });

  testWidgets('Hit test works properly on various parts of SliverCrossAxisGroup', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    String? clickedTile;

    int group = 0;
    int tile = 0;

    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        _buildSliverList(
          itemMainAxisExtent: 300,
          items: items,
          label: (int item) => tile == item && group == 0
            ? TextButton(
              onPressed: () => clickedTile = 'Group 0 Tile $item',
              child: Text('Group 0 Tile $item'),
            )
            : Text('Group 0 Tile $item'),
        ),
        _buildSliverList(
          items: items,
          label: (int item) => tile == item && group == 1
            ? TextButton(
              onPressed: () => clickedTile = 'Group 1 Tile $item',
              child: Text('Group 1 Tile $item'),
            )
            : Text('Group 1 Tile $item'),
        ),
      ]),
    );
    await tester.pumpAndSettle();
    await tester.tap(find.byType(TextButton));
    await tester.pumpAndSettle();
    expect(clickedTile, equals('Group 0 Tile 0'));

    clickedTile = null;
    group = 1;
    tile = 2;
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        _buildSliverList(
          itemMainAxisExtent: 300,
          items: items,
          label: (int item) => tile == item && group == 0
            ? TextButton(
              onPressed: () => clickedTile = 'Group 0 Tile $item',
              child: Text('Group 0 Tile $item'),
            )
            : Text('Group 0 Tile $item'),
        ),
        _buildSliverList(
          items: items,
          label: (int item) => tile == item && group == 1
            ? TextButton(
              onPressed: () => clickedTile = 'Group 1 Tile $item',
              child: Text('Group 1 Tile $item'),
            )
            : Text('Group 1 Tile $item'),
        ),
      ]),
    );
    await tester.pumpAndSettle();
    await tester.tap(find.byType(TextButton));
    await tester.pumpAndSettle();
    expect(clickedTile, equals('Group 1 Tile 2'));
  });

   testWidgets('Constrained sliver takes up remaining space', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverConstrainedCrossAxis(maxExtent: 200, sliver: _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item'))),
        SliverConstrainedCrossAxis(maxExtent: 200, sliver: _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item'))),
      ]),
    );
    await tester.pumpAndSettle();

    final List<RenderSliverList> renderSlivers = tester.renderObjectList<RenderSliverList>(find.byType(SliverList)).toList();
    final RenderSliverList first = renderSlivers[0];
    final RenderSliverList second = renderSlivers[1];

    expect(first.constraints.crossAxisExtent, equals(200));
    expect(second.constraints.crossAxisExtent, equals(100));

    // Check that their parent SliverConstrainedCrossAxis have the correct paintOffsets.
    final List<RenderSliverConstrainedCrossAxis> renderSliversConstrained = tester.renderObjectList<RenderSliverConstrainedCrossAxis>(find.byType(SliverConstrainedCrossAxis)).toList();
    final RenderSliverConstrainedCrossAxis firstConstrained = renderSliversConstrained[0];
    final RenderSliverConstrainedCrossAxis secondConstrained = renderSliversConstrained[1];

    expect((firstConstrained.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(0));
    expect((secondConstrained.parentData! as SliverPhysicalParentData).paintOffset.dx, equals(200));

    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject<RenderSliverCrossAxisGroup>(find.byType(SliverCrossAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
  });

  testWidgets('Assertion error when constrained widget runs out of cross axis extent', (WidgetTester tester) async {
    final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);

    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverConstrainedCrossAxis(maxExtent: 400, sliver: _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item'))),
        SliverConstrainedCrossAxis(maxExtent: 200, sliver: _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item'))),
      ]),
    );
    await tester.pumpAndSettle();
    FlutterError.onError = oldHandler;
    expect(errors, isNotEmpty);
    final AssertionError error = errors.first.exception as AssertionError;
    expect(
      error.toString(),
      contains('SliverCrossAxisGroup ran out of extent before child could be laid out.'),
    );
  });

  testWidgets('Assertion error when expanded widget runs out of cross axis extent', (WidgetTester tester) async {
    final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);

    final List<int> items = List<int>.generate(20, (int i) => i);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        SliverConstrainedCrossAxis(maxExtent: 200, sliver: _buildSliverList(itemMainAxisExtent: 300, items: items, label: (int item) => Text('Group 0 Tile $item'))),
        SliverConstrainedCrossAxis(maxExtent: 100, sliver: _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 1 Tile $item'))),
       _buildSliverList(itemMainAxisExtent: 200, items: items, label: (int item) => Text('Group 2 Tile $item')),
      ]),
    );
    await tester.pumpAndSettle();
    FlutterError.onError = oldHandler;
    expect(errors, isNotEmpty);
    final AssertionError error = errors.first.exception as AssertionError;
    expect(
      error.toString(),
      contains('SliverCrossAxisGroup ran out of extent before child could be laid out.'),
    );
  });

  testWidgets('applyPaintTransform is implemented properly', (WidgetTester tester) async {
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      slivers: <Widget>[
        const SliverToBoxAdapter(child: Text('first box')),
        const SliverToBoxAdapter(child: Text('second box')),
      ]),
    );
    await tester.pumpAndSettle();

    // localToGlobal calculates offset via applyPaintTransform
    final RenderBox first = tester.renderObject(find.text('first box'));
    final RenderBox second = tester.renderObject(find.text('second box'));
    expect(first.localToGlobal(Offset.zero), Offset.zero);
    expect(second.localToGlobal(Offset.zero), const Offset(VIEWPORT_WIDTH / 2, 0));
  });

  testWidgets('SliverPinnedPersistentHeader is painted within bounds of SliverCrossAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(),
          pinned: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    expect(renderGroup.geometry!.scrollExtent, equals(600));
    controller.jumpTo(560);
    await tester.pumpAndSettle();
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    // Paint extent after header's layout is 60.0, so we must offset by -20.0 to fit within the 40.0 remaining extent.
    expect(renderHeader.geometry!.paintExtent, equals(60.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-20.0));
  });

  testWidgets('SliverFloatingPersistentHeader is painted within bounds of SliverCrossAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(),
          floating: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    expect(renderGroup.geometry!.scrollExtent, equals(600));
    controller.jumpTo(600.0);
    await tester.pumpAndSettle();
    final TestGesture gesture = await tester.startGesture(const Offset(150.0, 300.0));
    await gesture.moveBy(const Offset(0.0, 40));
    await tester.pump();
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    // Paint extent after header's layout is 40.0, so no need to correct the paintOffset.
    expect(renderHeader.geometry!.paintExtent, equals(40.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
  });

  testWidgets('SliverPinnedPersistentHeader is painted within bounds of SliverCrossAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          pinned: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));
    controller.jumpTo(570);
    await tester.pumpAndSettle();
    // Paint extent of the header is 40.0, so we must provide an offset of -10.0 to make it fit in the 30.0 remaining paint extent of the group.
    expect(renderHeader.geometry!.paintExtent, equals(40.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-10.0));
    // Pinned headers should not expand to the maximum extent unless the scroll offset is at the top of the sliver group.
    controller.jumpTo(550);
    await tester.pumpAndSettle();
    expect(renderHeader.geometry!.paintExtent, equals(40.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
  });

  testWidgets('SliverFloatingPersistentHeader is painted within bounds of SliverCrossAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          floating: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();

    final TestGesture gesture = await tester.startGesture(const Offset(150.0, 300.0));
    await gesture.moveBy(const Offset(0.0, 30.0));
    await tester.pump();
    // Paint extent after header's layout is 30.0, so no need to correct the paintOffset.
    expect(renderHeader.geometry!.paintExtent, equals(30.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
    // Floating headers should expand to maximum extent as we continue scrolling.
    await gesture.moveBy(const Offset(0.0, 20.0));
    await tester.pump();
    expect(renderHeader.geometry!.paintExtent, equals(50.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
  });

  testWidgets('SliverPinnedFloatingPersistentHeader is painted within bounds of SliverCrossAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          pinned: true,
          floating: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();

    final TestGesture gesture = await tester.startGesture(const Offset(150.0, 300.0));
    await gesture.moveBy(const Offset(0.0, 30.0));
    await tester.pump();
    // Paint extent after header's layout is 40.0, so we need to adjust by -10.0.
    expect(renderHeader.geometry!.paintExtent, equals(40.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-10.0));
    // Pinned floating headers should expand to maximum extent as we continue scrolling.
    await gesture.moveBy(const Offset(0.0, 20.0));
    await tester.pump();
    expect(renderHeader.geometry!.paintExtent, equals(50.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
  });

  testWidgets('SliverAppBar with floating: false, pinned: false, snap: false is painted within bounds of SliverCrossAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();
    controller.jumpTo(570);
    await tester.pumpAndSettle();

    // At a scroll offset of 570, a normal scrolling header should be out of view.
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderHeader.geometry!.paintExtent, equals(0.0));
  });

  testWidgets('SliverAppBar with floating: true, pinned: false, snap: true is painted within bounds of SliverCrossAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
          floating: true,
          snap: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();

    final TestGesture gesture = await tester.startGesture(const Offset(150.0, 300.0));
    await gesture.moveBy(const Offset(0.0, 10));
    await tester.pump();

    // The snap animation does not go through until the gesture is released.
    expect(renderHeader.geometry!.paintExtent, equals(10));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));

    // Once it is released, the header's paint extent becomes the maximum and the group sets an offset of -50.0.
    await gesture.up();
    await tester.pumpAndSettle();
    expect(renderHeader.geometry!.paintExtent, equals(60));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0));
  });

  testWidgets('SliverAppBar with floating: true, pinned: true, snap: true is painted within bounds of SliverCrossAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
          floating: true,
          pinned: true,
          snap: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();

    final TestGesture gesture = await tester.startGesture(const Offset(150.0, 300.0));
    await gesture.moveBy(const Offset(0.0, 10));
    await tester.pump();

    expect(renderHeader.geometry!.paintExtent, equals(30.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-20.0));

    // Once we lift the gesture up, the animation should finish.
    await gesture.up();
    await tester.pumpAndSettle();
    expect(renderHeader.geometry!.paintExtent, equals(60.0));
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0));
  });

  testWidgets('SliverFloatingPersistentHeader scroll direction is not affected by controller.jumpTo', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(_buildSliverCrossAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
        SliverPersistentHeader(
          delegate: TestDelegate(),
          floating: true,
        ),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverCrossAxisGroup renderGroup = tester.renderObject(find.byType(SliverCrossAxisGroup)) as RenderSliverCrossAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(600));

    controller.jumpTo(600);
    await tester.pumpAndSettle();
    controller.jumpTo(570);
    await tester.pumpAndSettle();

    // If renderHeader._lastStartedScrollDirection is not ScrollDirection.forward, then we shouldn't see the header at all.
    expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
  });

  testWidgets('SliverCrossAxisGroup skips painting invisible children', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    int counter = 0;
    void incrementCounter() {
      counter += 1;
    }

    await tester.pumpWidget(
      _buildSliverCrossAxisGroup(
        controller: controller,
        slivers: <Widget>[
          MockSliverToBoxAdapter(
            incrementCounter: incrementCounter,
            child: Container(
              height: 1000,
              decoration: const BoxDecoration(color: Colors.amber),
            ),
          ),
          MockSliverToBoxAdapter(
            incrementCounter: incrementCounter,
            child: Container(
              height: 400,
              decoration: const BoxDecoration(color: Colors.amber)
            ),
          ),
          MockSliverToBoxAdapter(
            incrementCounter: incrementCounter,
            child: Container(
              height: 500,
              decoration: const BoxDecoration(color: Colors.amber)
            ),
          ),
          MockSliverToBoxAdapter(
            incrementCounter: incrementCounter,
            child: Container(
              height: 300,
              decoration: const BoxDecoration(color: Colors.amber)
            ),
          ),
        ],
      ),
    );
    expect(counter, equals(4));

    // Reset paint counter.
    counter = 0;
    controller.jumpTo(400);
    await tester.pumpAndSettle();

    expect(controller.offset, 400);
    expect(counter, equals(2));
  });
}


Widget _buildSliverList({
  double itemMainAxisExtent = 100,
  List<int> items = const <int>[],
  required Widget Function(int) label,
  Axis scrollDirection = Axis.vertical,
}) {
  return SliverList(
    delegate: SliverChildBuilderDelegate(
      (BuildContext context, int i) {
        return scrollDirection == Axis.vertical
          ? SizedBox(
            key: ValueKey<int>(items[i]),
            height: itemMainAxisExtent,
            child: label(items[i]),
          )
          : SizedBox(
            key: ValueKey<int>(items[i]),
            width: itemMainAxisExtent,
            child: label(items[i]));
      },
      findChildIndexCallback: (Key key) {
        final ValueKey<int> valueKey = key as ValueKey<int>;
        final int index = items.indexOf(valueKey.value);
        return index == -1 ? null : index;
      },
      childCount: items.length,
    ),
  );
}

Widget _buildSliverCrossAxisGroup({
  required List<Widget> slivers,
  ScrollController? controller,
  double viewportHeight = VIEWPORT_HEIGHT,
  double viewportWidth = VIEWPORT_WIDTH,
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  List<Widget> otherSlivers = const <Widget>[],
}) {
  return MaterialApp(
    home: Directionality(
      textDirection: TextDirection.ltr,
      child: Align(
        alignment: Alignment.topLeft,
        child: SizedBox(
          height: viewportHeight,
          width: viewportWidth,
          child: CustomScrollView(
            scrollDirection: scrollDirection,
            reverse: reverse,
            controller: controller,
            slivers: <Widget>[SliverCrossAxisGroup(slivers: slivers), ...otherSlivers],
          ),
        ),
      ),
    )
  );
}

class TestDelegate extends SliverPersistentHeaderDelegate {
  TestDelegate({ this.maxExtent = 60.0, this.minExtent = 60.0 });

  @override
  final double maxExtent;

  @override
  final double minExtent;

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(height: maxExtent);
  }

  @override
  bool shouldRebuild(TestDelegate oldDelegate) => true;
}
