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

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


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

void main() {
  testWidgets('SliverMainAxisGroup 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(
      _buildSliverMainAxisGroup(
        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(
      tester.getRect(find.text('Group 0 Tile 0')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
    );
    expect(find.text('Group 0 Tile 1'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 1')),
      const Rect.fromLTRB(0.0, 300.0, 300.0, 600.0),
    );
    expect(find.text('Group 0 Tile 2'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsNothing);

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

    expect(controller.offset, scrollOffset);
    expect(find.text('Group 0 Tile 18'), findsNothing);
    expect(find.text('Group 0 Tile 19'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 19')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
    );
    expect(find.text('Group 1 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 1 Tile 0')),
      const Rect.fromLTRB(0.0, 300.0, 300.0, 500.0),
    );

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

    expect(first.geometry!.layoutExtent, equals(300.0));
    expect(second.geometry!.layoutExtent, equals(300.0));
    expect(first.geometry!.scrollExtent, equals(20 * 300.0));
    expect(second.geometry!.scrollExtent, equals(20 * 200.0));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
    expect(first.constraints.scrollOffset, equals(19 * 300.0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(1 * 300.0));

    final RenderSliverMainAxisGroup renderGroup =
        tester.renderObject<RenderSliverMainAxisGroup>(find.byType(SliverMainAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20 + 200 * 20));
    expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
  });

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

    await tester.pumpWidget(
      _buildSliverMainAxisGroup(
        controller: controller,
        reverse: true,
        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(
      tester.getRect(find.text('Group 0 Tile 0')),
      const Rect.fromLTRB(0.0, 300.0, 300.0, 600.0),
    );
    expect(find.text('Group 0 Tile 1'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 1')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
    );
    expect(find.text('Group 0 Tile 2'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsNothing);

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

    expect(controller.offset, scrollOffset);
    expect(find.text('Group 0 Tile 18'), findsNothing);
    expect(find.text('Group 0 Tile 19'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 19')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 300.0),
    );
    expect(find.text('Group 1 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 1 Tile 0')),
      const Rect.fromLTRB(0.0, 400.0, 300.0, 600.0),
    );

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

    expect(first.geometry!.layoutExtent, equals(300.0));
    expect(second.geometry!.layoutExtent, equals(300.0));
    expect(first.geometry!.scrollExtent, equals(20 * 300.0));
    expect(second.geometry!.scrollExtent, equals(20 * 200.0));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
    expect(first.constraints.scrollOffset, equals(19 * 300.0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(1 * 300.0));

    final RenderSliverMainAxisGroup renderGroup =
        tester.renderObject<RenderSliverMainAxisGroup>(find.byType(SliverMainAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20 + 200 * 20));
    expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
  });

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

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

    expect(controller.offset, 0);

    expect(find.text('Group 0 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 0')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
    );
    expect(find.text('Group 0 Tile 1'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsNothing);

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

    expect(controller.offset, scrollOffset);
    expect(find.text('Group 0 Tile 18'), findsNothing);
    expect(find.text('Group 0 Tile 19'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 19')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
    );
    expect(find.text('Group 1 Tile 0'), findsNothing);

    const double scrollOffset2 = 20 * 300.0;
    controller.jumpTo(scrollOffset2);
    await tester.pumpAndSettle();
    expect(find.text('Group 0 Tile 19'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 1 Tile 0')),
      const Rect.fromLTRB(0.0, 0.0, 200.0, 600.0),
    );

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

    expect(first.geometry!.layoutExtent, equals(0.0));
    expect(second.geometry!.layoutExtent, equals(300.0));
    expect(first.geometry!.scrollExtent, equals(20 * 300.0));
    expect(second.geometry!.scrollExtent, equals(20 * 200.0));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
    expect(first.constraints.scrollOffset, equals(20 * 300.0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));

    final RenderSliverMainAxisGroup renderGroup =
        tester.renderObject<RenderSliverMainAxisGroup>(find.byType(SliverMainAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20 + 200 * 20));
    expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
  });

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

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

    expect(controller.offset, 0);

    expect(find.text('Group 0 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 0')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
    );
    expect(find.text('Group 0 Tile 1'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsNothing);

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

    expect(controller.offset, scrollOffset);
    expect(find.text('Group 0 Tile 18'), findsNothing);
    expect(find.text('Group 0 Tile 19'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 0 Tile 19')),
      const Rect.fromLTRB(0.0, 0.0, 300.0, 600.0),
    );
    expect(find.text('Group 1 Tile 0'), findsNothing);

    const double scrollOffset2 = 20 * 300.0;
    controller.jumpTo(scrollOffset2);
    await tester.pumpAndSettle();
    expect(find.text('Group 0 Tile 19'), findsNothing);
    expect(find.text('Group 1 Tile 0'), findsOneWidget);
    expect(
      tester.getRect(find.text('Group 1 Tile 0')),
      const Rect.fromLTRB(100.0, 0.0, 300.0, 600.0),
    );

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

    expect(first.geometry!.layoutExtent, equals(0.0));
    expect(second.geometry!.layoutExtent, equals(300.0));
    expect(first.geometry!.scrollExtent, equals(20 * 300.0));
    expect(second.geometry!.scrollExtent, equals(20 * 200.0));

    expect((first.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
    expect(first.constraints.scrollOffset, equals(20 * 300.0));
    expect((second.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));

    final RenderSliverMainAxisGroup renderGroup =
        tester.renderObject<RenderSliverMainAxisGroup>(find.byType(SliverMainAxisGroup));
    expect(renderGroup.geometry!.scrollExtent, equals(300 * 20 + 200 * 20));
    expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
  });

  testWidgets('Hit test works properly on various parts of SliverMainAxisGroup', (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(_buildSliverMainAxisGroup(
      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(_buildSliverMainAxisGroup(
      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'),
        ),
      ]),
    );
    controller.jumpTo(300.0 * 20);
    await tester.pumpAndSettle();
    await tester.tap(find.byType(TextButton));
    await tester.pumpAndSettle();
    expect(clickedTile, equals('Group 1 Tile 2'));
  });

  testWidgets('applyPaintTransform is implemented properly', (WidgetTester tester) async {
    await tester.pumpWidget(_buildSliverMainAxisGroup(
      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')) as RenderBox;
    final RenderBox second = tester.renderObject(find.text('second box'));
    expect(first.localToGlobal(Offset.zero), Offset.zero);
    expect(second.localToGlobal(Offset.zero), Offset(0, first.size.height));
  });

  testWidgets('visitChildrenForSemantics visits children in the correct order', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: const <Widget>[
        SliverToBoxAdapter(child: SizedBox(height: 200)),
        SliverToBoxAdapter(child: SizedBox(height: 300)),
        SliverToBoxAdapter(child: SizedBox(height: 500)),
        SliverToBoxAdapter(child: SizedBox(height: 400)),
      ]),
    );
    controller.jumpTo(300);
    await tester.pumpAndSettle();

    final List<RenderSliver> visitedChildren = <RenderSliver>[];
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject<RenderSliverMainAxisGroup>(find.byType(SliverMainAxisGroup));
    void visitor(RenderObject child) {
      visitedChildren.add(child as RenderSliver);
    }
    renderGroup.visitChildrenForSemantics(visitor);
    expect(visitedChildren.length, equals(2));
    expect(visitedChildren[0].geometry!.scrollExtent, equals(300));
    expect(visitedChildren[1].geometry!.scrollExtent, equals(500));
  });

  testWidgets('SliverPinnedPersistentHeader is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        SliverPersistentHeader(
          delegate: TestDelegate(),
          pinned: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    // Scroll extent is the total of the box sliver and the sliver persistent header.
    expect(renderGroup.geometry!.scrollExtent, equals(600.0 + 60.0));
    controller.jumpTo(620);
    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 SliverMainAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        SliverPersistentHeader(
          delegate: TestDelegate(),
          floating: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    expect(renderGroup.geometry!.scrollExtent, equals(660));
    controller.jumpTo(660.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 SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          pinned: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(660));
    controller.jumpTo(630);
    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));
    controller.jumpTo(610);
    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 SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          floating: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(660));

    controller.jumpTo(660);
    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 SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        SliverPersistentHeader(
          delegate: TestDelegate(minExtent: 40.0),
          pinned: true,
          floating: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(660));

    controller.jumpTo(660);
    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 SliverMainAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    expect(renderGroup.geometry!.scrollExtent, equals(660));

    controller.jumpTo(660);
    await tester.pumpAndSettle();
    controller.jumpTo(630);
    await tester.pumpAndSettle();

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

    testWidgets('SliverAppBar with floating: true, pinned: false, snap: true is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
          floating: true,
          snap: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(660));

    controller.jumpTo(660);
    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 SliverMainAxisGroup', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

    await tester.pumpWidget(_buildSliverMainAxisGroup(
      controller: controller,
      slivers: <Widget>[
        const SliverAppBar(
          toolbarHeight: 30,
          expandedHeight: 60,
          floating: true,
          pinned: true,
          snap: true,
        ),
        const SliverToBoxAdapter(child: SizedBox(height: 600)),
      ],
      otherSlivers: <Widget>[
        const SliverToBoxAdapter(child: SizedBox(height: 2400)),
      ],
    ));
    await tester.pumpAndSettle();
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(find.byType(SliverMainAxisGroup)) as RenderSliverMainAxisGroup;
    final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader)) as RenderSliverPersistentHeader;
    expect(renderGroup.geometry!.scrollExtent, equals(660));

    controller.jumpTo(660);
    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('SliverMainAxisGroup skips painting invisible children', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    addTearDown(controller.dispose);

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

    await tester.pumpWidget(
      _buildSliverMainAxisGroup(
        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)
            ),
          ),
        ],
      ),
    );

    // Can only see top sliver.
    expect(counter, equals(1));

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

    // Can only see second and third slivers.
    expect(controller.offset, 1000);
    expect(counter, equals(2));
  });

  testWidgets('SliverMainAxisGroup does not cause extra builds for lazy sliver children', (WidgetTester tester) async {
    // By setting the correct SliverGeometry in the first SliverMainAxisGroup,
    // the following SliverMainAxisGroups will not perform extra work.
    final Map<int, int> buildsPerGroup = <int, int>{
      0 : 0,
      1 : 0,
      2 : 0,
    };
    await tester.pumpWidget(MaterialApp(
      home: CustomScrollView(
        slivers: <Widget>[
          for (int groupIndex = 0; groupIndex < 3; groupIndex++)
            SliverMainAxisGroup(
              slivers: <Widget>[
                SliverList.builder(
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    buildsPerGroup[groupIndex] = buildsPerGroup[groupIndex]! + 1;
                    return const SizedBox.square(dimension: 50);
                  },
                ),
              ],
            ),
        ]
      ),
    ));
    await tester.pumpAndSettle();
    expect(buildsPerGroup[0], 17); // First sliver filled the screen and cache extent
    expect(buildsPerGroup[1], 1); // Second only lays out one child
    expect(buildsPerGroup[2], 1); // Third only lays out one child
    final RenderSliverMainAxisGroup renderGroup = tester.renderObject(
        find.byType(SliverMainAxisGroup).first,
    ) as RenderSliverMainAxisGroup;
    expect(renderGroup.geometry!.cacheExtent, 850.0);
  });

  testWidgets('SliverMainAxisGroup correctly handles ensureVisible', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      _buildSliverMainAxisGroup(
        viewportHeight: 300,
        slivers: <Widget>[
          const SliverToBoxAdapter(child: SizedBox(height: 300)),
          SliverToBoxAdapter(child: SizedBox(key: key, height: 100)),
          const SliverToBoxAdapter(child: SizedBox(height: 300)),
        ]
      )
    );
    Scrollable.ensureVisible(key.currentContext!);
    await tester.pumpAndSettle();
    expect(tester.getTopLeft(find.byKey(key)), Offset.zero);
  });
}

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 _buildSliverMainAxisGroup({
  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>[SliverMainAxisGroup(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;
}
