@@ -6,6 +6,8 @@ import 'package:flutter/widgets.dart' hide SliverPaintOrder;
66import 'package:flutter_test/flutter_test.dart' ;
77import 'package:zulip/widgets/scrolling.dart' ;
88
9+ import '../flutter_checks.dart' ;
10+
911void main () {
1012 group ('CustomPaintOrderScrollView paint order' , () {
1113 final paintLog = < int > [];
@@ -127,6 +129,78 @@ void main() {
127129 .deepEquals (sliverIds (result.path));
128130 });
129131 });
132+
133+ group ('MessageListScrollView' , () {
134+ Future <void > prepare (WidgetTester tester,
135+ {required double topHeight, required double bottomHeight}) async {
136+ await tester.pumpWidget (Directionality (textDirection: TextDirection .ltr,
137+ child: MessageListScrollView (
138+ controller: MessageListScrollController (),
139+ center: const ValueKey ('center' ),
140+ slivers: [
141+ SliverToBoxAdapter (
142+ child: SizedBox (height: topHeight, child: Text ('top' ))),
143+ SliverToBoxAdapter (key: const ValueKey ('center' ),
144+ child: SizedBox (height: bottomHeight, child: Text ('bottom' ))),
145+ ])));
146+ await tester.pump ();
147+ }
148+
149+ // The `skipOffstage: false` produces more informative output
150+ // when a test fails because one of the slivers is just offscreen.
151+ final findTop = find.text ('top' , skipOffstage: false );
152+ final findBottom = find.text ('bottom' , skipOffstage: false );
153+
154+ testWidgets ('short/short -> starts scrolled to bottom' , (tester) async {
155+ // Starts out with items at bottom of viewport.
156+ await prepare (tester, topHeight: 100 , bottomHeight: 100 );
157+ check (tester.getRect (findBottom)).bottom.equals (600 );
158+
159+ // Try scrolling down (by dragging up); doesn't move.
160+ await tester.drag (findTop, Offset (0 , - 100 ));
161+ await tester.pump ();
162+ check (tester.getRect (findBottom)).bottom.equals (600 );
163+ });
164+
165+ testWidgets ('short/long -> starts scrolled to bottom' , (tester) async {
166+ // Starts out scrolled to bottom.
167+ await prepare (tester, topHeight: 100 , bottomHeight: 800 );
168+ check (tester.getRect (findBottom)).bottom.equals (600 );
169+
170+ // Try scrolling down (by dragging up); doesn't move.
171+ await tester.drag (findBottom, Offset (0 , - 100 ));
172+ await tester.pump ();
173+ check (tester.getRect (findBottom)).bottom.equals (600 );
174+ });
175+
176+ testWidgets ('starts at bottom, even when bottom underestimated at first' , (tester) async {
177+ const numItems = 10 ;
178+ const itemHeight = 300.0 ;
179+
180+ // A list where the bottom sliver takes several rounds of layout
181+ // to see how long it really is.
182+ final controller = MessageListScrollController ();
183+ await tester.pumpWidget (Directionality (textDirection: TextDirection .ltr,
184+ child: MessageListScrollView (
185+ controller: controller,
186+ center: const ValueKey ('center' ),
187+ slivers: [
188+ SliverToBoxAdapter (
189+ child: SizedBox (height: 100 , child: Text ('top' ))),
190+ SliverList .list (key: const ValueKey ('center' ),
191+ children: List .generate (numItems, (i) =>
192+ SizedBox (height: (i+ 1 ) * itemHeight, child: Text ('item $i ' )))),
193+ ])));
194+ await tester.pump ();
195+
196+ // Starts out scrolled all the way to the bottom,
197+ // even though it must have taken several rounds of layout to find that.
198+ check (controller.position.pixels)
199+ .equals (itemHeight * numItems * (numItems + 1 )/ 2 );
200+ check (tester.getRect (find.text ('item ${numItems -1 }' , skipOffstage: false )))
201+ .bottom.equals (600 );
202+ });
203+ });
130204}
131205
132206class TestCustomPainter extends CustomPainter {
0 commit comments