From 7b262d926d663b33f32cb2c47b77071289ffc1d0 Mon Sep 17 00:00:00 2001 From: yim Date: Wed, 11 Dec 2024 08:58:59 +0800 Subject: [PATCH] Test `SliverMainAxisGroup` offstage child (#159406) ```dart import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('my test', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: LayoutBuilder( builder: (context, view) { return CustomScrollView( slivers: [ SliverMainAxisGroup( slivers: [ SliverToBoxAdapter(child: SizedBox(height: view.maxHeight)), const SliverToBoxAdapter(child: Text('1')), ], ) ], ); }, ), ), ); expect(find.text('1'), findsNothing); }); } ``` The above test should have passed, but it failed. This PR fixes the issue. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --- .../sliver/sliver_main_axis_group.0_test.dart | 11 +++++++++- packages/flutter/lib/src/widgets/sliver.dart | 15 ++++++++++++++ .../test/widgets/editable_text_test.dart | 2 +- .../widgets/sliver_main_axis_group_test.dart | 20 ++++++++++++++++--- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/examples/api/test/widgets/sliver/sliver_main_axis_group.0_test.dart b/examples/api/test/widgets/sliver/sliver_main_axis_group.0_test.dart index 563b54739d..4bf4e15abe 100644 --- a/examples/api/test/widgets/sliver/sliver_main_axis_group.0_test.dart +++ b/examples/api/test/widgets/sliver/sliver_main_axis_group.0_test.dart @@ -19,7 +19,16 @@ void main() { final RenderSliverPersistentHeader renderAppBar = tester.renderObject(find.byType(SliverAppBar)); final RenderSliverList renderSliverList = tester.renderObject(find.byType(SliverList)); - final RenderSliverToBoxAdapter renderSliverAdapter = tester.renderObject(find.byType(SliverToBoxAdapter)); + final RenderSliverToBoxAdapter renderSliverAdapter = tester.renderObject( + find.descendant( + of: find.byType(SliverMainAxisGroup), + matching: find.byType( + SliverToBoxAdapter, + skipOffstage: false, + ), + skipOffstage: false, + ), + ); // renderAppBar, renderSliverList, and renderSliverAdapter1 are part of the same sliver group. expect(renderAppBar.geometry!.scrollExtent, equals(70.0)); diff --git a/packages/flutter/lib/src/widgets/sliver.dart b/packages/flutter/lib/src/widgets/sliver.dart index facab53b50..17abc49f67 100644 --- a/packages/flutter/lib/src/widgets/sliver.dart +++ b/packages/flutter/lib/src/widgets/sliver.dart @@ -1741,8 +1741,23 @@ class SliverMainAxisGroup extends MultiChildRenderObjectWidget { required List slivers, }) : super(children: slivers); + @override + MultiChildRenderObjectElement createElement() => _SliverMainAxisGroupElement(this); + @override RenderSliverMainAxisGroup createRenderObject(BuildContext context) { return RenderSliverMainAxisGroup(); } } + +class _SliverMainAxisGroupElement extends MultiChildRenderObjectElement { + _SliverMainAxisGroupElement(SliverMainAxisGroup super.widget); + + @override + void debugVisitOnstageChildren(ElementVisitor visitor) { + children.where((Element e) { + final RenderSliver renderSliver = e.renderObject! as RenderSliver; + return renderSliver.geometry!.visible; + }).forEach(visitor); + } +} diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 2f5f705f6f..77940709ef 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -16960,7 +16960,7 @@ void main() { ), ); await tester.pumpWidget(widget); - await tester.showKeyboard(find.byType(EditableText)); + await tester.showKeyboard(find.byType(EditableText, skipOffstage: false)); await tester.pumpAndSettle(); expect(scrollController.offset, 75.0); }); diff --git a/packages/flutter/test/widgets/sliver_main_axis_group_test.dart b/packages/flutter/test/widgets/sliver_main_axis_group_test.dart index 7c9239972b..7e84f0237a 100644 --- a/packages/flutter/test/widgets/sliver_main_axis_group_test.dart +++ b/packages/flutter/test/widgets/sliver_main_axis_group_test.dart @@ -198,7 +198,7 @@ void main() { const Rect.fromLTRB(0.0, 0.0, 200.0, 600.0), ); - final List renderSlivers = tester.renderObjectList(find.byType(SliverList)).toList(); + final List renderSlivers = tester.renderObjectList(find.byType(SliverList, skipOffstage: false)).toList(); final RenderSliverList first = renderSlivers[0]; final RenderSliverList second = renderSlivers[1]; @@ -268,7 +268,7 @@ void main() { const Rect.fromLTRB(100.0, 0.0, 300.0, 600.0), ); - final List renderSlivers = tester.renderObjectList(find.byType(SliverList)).toList(); + final List renderSlivers = tester.renderObjectList(find.byType(SliverList, skipOffstage: false)).toList(); final RenderSliverList first = renderSlivers[0]; final RenderSliverList second = renderSlivers[1]; @@ -598,7 +598,7 @@ void main() { 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; + final RenderSliverPersistentHeader renderHeader = tester.renderObject(find.byType(SliverPersistentHeader, skipOffstage: false)) as RenderSliverPersistentHeader; expect(renderHeader.constraints.scrollOffset, equals(630)); expect(renderHeader.geometry!.layoutExtent, equals(0.0)); }); @@ -855,6 +855,20 @@ void main() { expect(tester.getTopLeft(find.byKey(firstTextFieldKey)), const Offset(0, 60)); }); + + testWidgets('SliverMainAxisGroup offstage child', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverMainAxisGroup( + viewportHeight: 300, + slivers: [ + const SliverToBoxAdapter(child: SizedBox(height: 300)), + const SliverToBoxAdapter(child: SizedBox(height: 100, child: Text('1'))), + ] + ) + ); + expect(find.text('1'), findsNothing); + expect(find.text('1', skipOffstage: false), findsOneWidget); + }); } Widget _buildSliverList({