@@ -51,6 +51,11 @@ void main() {
51
51
await tester.pumpAndSettle ();
52
52
}
53
53
54
+ List <StreamMessage > generateStreamMessages (ZulipStream stream, int count) {
55
+ return List .generate (count, (index) => eg.streamMessage (
56
+ stream: stream, topic: '${stream .name } topic $index ' , flags: []));
57
+ }
58
+
54
59
/// Set up an inbox view with lots of interesting content.
55
60
Future <void > setupVarious (WidgetTester tester) async {
56
61
final stream1 = eg.stream (streamId: 1 , name: 'stream 1' );
@@ -61,12 +66,16 @@ void main() {
61
66
await setupPage (tester,
62
67
streams: [stream1, stream2],
63
68
subscriptions: [sub1, sub2],
64
- users: [eg.selfUser, eg.otherUser, eg.thirdUser],
69
+ users: [eg.selfUser, eg.otherUser, eg.thirdUser, eg.fourthUser ],
65
70
unreadMessages: [
66
71
eg.streamMessage (stream: stream1, topic: 'specific topic' , flags: []),
72
+ ...generateStreamMessages (stream1, 10 ),
67
73
eg.streamMessage (stream: stream2, flags: []),
74
+ ...generateStreamMessages (stream2, 40 ),
68
75
eg.dmMessage (from: eg.otherUser, to: [eg.selfUser], flags: []),
69
76
eg.dmMessage (from: eg.otherUser, to: [eg.selfUser, eg.thirdUser], flags: []),
77
+ eg.dmMessage (from: eg.thirdUser, to: [eg.selfUser], flags: []),
78
+ eg.dmMessage (from: eg.fourthUser, to: [eg.selfUser], flags: []),
70
79
]);
71
80
}
72
81
@@ -252,6 +261,28 @@ void main() {
252
261
|| widget.icon == ZulipIcons .arrow_right))));
253
262
}
254
263
264
+ Future <void > dragUntilInvisible (
265
+ WidgetTester tester,
266
+ FinderBase <Element > finder,
267
+ FinderBase <Element > view,
268
+ Offset moveStep, {
269
+ int maxIteration = 50 ,
270
+ Duration duration = const Duration (milliseconds: 50 ),
271
+ }) {
272
+ return TestAsyncUtils .guard <void >(() async {
273
+ final iteration = maxIteration;
274
+ while (maxIteration > 0 && finder.evaluate ().isNotEmpty) {
275
+ await tester.drag (view, moveStep);
276
+ await tester.pump (duration);
277
+ maxIteration -= 1 ;
278
+ }
279
+ if (maxIteration <= 0 && finder.evaluate ().isNotEmpty) {
280
+ throw StateError (
281
+ 'Finder is still visible after $iteration iterations. Consider increasing the number of iterations.' );
282
+ }
283
+ });
284
+ }
285
+
255
286
group ('all-DMs section' , () {
256
287
Future <void > tapCollapseIcon (WidgetTester tester) async {
257
288
final headerRow = findAllDmsHeaderRow (tester);
@@ -310,6 +341,30 @@ void main() {
310
341
checkAppearsUncollapsed (tester, findSectionContent);
311
342
});
312
343
344
+ testWidgets ('collapse all-DMs section after scroll' , (tester) async {
345
+ await setupVarious (tester);
346
+
347
+ final listFinder = find.byType (Scrollable );
348
+ final findSectionContent =
349
+ find.text (eg.otherUser.fullName).hitTestable ();
350
+
351
+ // Scroll the [StickyHeaderListView] enough so that
352
+ // the [_AllDmsSection] shows a sticky header
353
+ await dragUntilInvisible (
354
+ tester, findSectionContent, listFinder, const Offset (0 , - 50 ));
355
+
356
+ Widget ? headerRow = findAllDmsHeaderRow (tester);
357
+ // Check that the header is present (which in this case
358
+ // is a sticky one as we've scrolled enough)
359
+ check (headerRow).isNotNull ();
360
+
361
+ await tapCollapseIcon (tester);
362
+ // Check that the header is still visible even after
363
+ // collapsing the section
364
+ headerRow = findAllDmsHeaderRow (tester);
365
+ check (headerRow).isNotNull ();
366
+ });
367
+
313
368
// TODO check it remains collapsed even if you scroll far away and back
314
369
315
370
// TODO check that it's always uncollapsed when it appears after being
@@ -325,7 +380,7 @@ void main() {
325
380
check (headerRow).isNotNull ();
326
381
final icon = findHeaderCollapseIcon (tester, headerRow! );
327
382
await tester.tap (find.byWidget (icon));
328
- await tester.pump ();
383
+ await tester.pumpAndSettle ();
329
384
}
330
385
331
386
/// Check that the section appears uncollapsed.
@@ -385,6 +440,29 @@ void main() {
385
440
checkAppearsUncollapsed (tester, 1 , findSectionContent);
386
441
});
387
442
443
+ testWidgets ('collapse stream section after scroll' , (tester) async {
444
+ await setupVarious (tester);
445
+
446
+ final topicFinder = find.text ('stream 1 topic 4' ).hitTestable ();
447
+ final listFinder = find.byType (Scrollable );
448
+
449
+ // Scroll the [StickyHeaderListView] enough so that
450
+ // the [_StreamSection] shows a sticky header
451
+ await dragUntilInvisible (
452
+ tester, topicFinder, listFinder, const Offset (0 , - 100 ));
453
+
454
+ Widget ? headerRow = findStreamHeaderRow (tester, 1 );
455
+ // Check that the header is present (which in this case
456
+ // is a sticky one as we've scrolled enough)
457
+ check (headerRow).isNotNull ();
458
+
459
+ await tapCollapseIcon (tester, 1 );
460
+ // Check that the header is still visible even after
461
+ // collapsing the section
462
+ headerRow = findStreamHeaderRow (tester, 1 );
463
+ check (headerRow).isNotNull ();
464
+ });
465
+
388
466
// TODO check it remains collapsed even if you scroll far away and back
389
467
390
468
// TODO check that it's always uncollapsed when it appears after being
@@ -393,6 +471,8 @@ void main() {
393
471
// reappear because a new unread arrived, but with #346 it could also
394
472
// reappear because you unmuted a conversation.)
395
473
});
474
+
475
+
396
476
});
397
477
});
398
478
}
0 commit comments