@@ -294,6 +294,170 @@ void main() {
294
294
});
295
295
});
296
296
297
+ group ('MarkAsReadWidget' , () {
298
+ bool isMarkAsReadButtonVisible (WidgetTester tester) {
299
+ final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
300
+ final finder = find.text (
301
+ zulipLocalizations.markAllAsReadLabel).hitTestable ();
302
+ return finder.evaluate ().isNotEmpty;
303
+ }
304
+
305
+ testWidgets ('from read to unread' , (WidgetTester tester) async {
306
+ final message = eg.streamMessage (flags: [MessageFlag .read]);
307
+ await setupMessageListPage (tester, messages: [message]);
308
+ check (isMarkAsReadButtonVisible (tester)).isFalse ();
309
+
310
+ await store.handleEvent (eg.updateMessageFlagsRemoveEvent (
311
+ MessageFlag .read, [message]));
312
+ await tester.pumpAndSettle ();
313
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
314
+ });
315
+
316
+ testWidgets ('from unread to read' , (WidgetTester tester) async {
317
+ final message = eg.streamMessage (flags: []);
318
+ final unreadMsgs = eg.unreadMsgs (streams: [
319
+ UnreadStreamSnapshot (topic: message.topic, streamId: message.streamId, unreadMessageIds: [message.id])
320
+ ]);
321
+ await setupMessageListPage (tester, messages: [message], unreadMsgs: unreadMsgs);
322
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
323
+
324
+ await store.handleEvent (UpdateMessageFlagsAddEvent (
325
+ id: 1 ,
326
+ flag: MessageFlag .read,
327
+ messages: [message.id],
328
+ all: false ,
329
+ ));
330
+ await tester.pumpAndSettle ();
331
+ check (isMarkAsReadButtonVisible (tester)).isFalse ();
332
+ });
333
+
334
+ testWidgets ("messages don't shift position" , (WidgetTester tester) async {
335
+ final message = eg.streamMessage (flags: []);
336
+ final unreadMsgs = eg.unreadMsgs (streams: [
337
+ UnreadStreamSnapshot (topic: message.topic, streamId: message.streamId,
338
+ unreadMessageIds: [message.id])
339
+ ]);
340
+ await setupMessageListPage (tester,
341
+ messages: [message], unreadMsgs: unreadMsgs);
342
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
343
+ check (tester.widgetList (find.byType (MessageItem ))).length.equals (1 );
344
+ final before = tester.getTopLeft (find.byType (MessageItem )).dy;
345
+
346
+ await store.handleEvent (UpdateMessageFlagsAddEvent (
347
+ id: 1 ,
348
+ flag: MessageFlag .read,
349
+ messages: [message.id],
350
+ all: false ,
351
+ ));
352
+ await tester.pumpAndSettle ();
353
+ check (isMarkAsReadButtonVisible (tester)).isFalse ();
354
+ check (tester.widgetList (find.byType (MessageItem ))).length.equals (1 );
355
+ final after = tester.getTopLeft (find.byType (MessageItem )).dy;
356
+ check (after).equals (before);
357
+ });
358
+
359
+ group ('onPressed behavior' , () {
360
+ // The markNarrowAsRead function has detailed unit tests of its own.
361
+ // These tests cover functionality that's outside that function,
362
+ // and a couple of smoke tests showing this button is wired up to it.
363
+
364
+ final message = eg.streamMessage (flags: []);
365
+ final unreadMsgs = eg.unreadMsgs (streams: [
366
+ UnreadStreamSnapshot (streamId: message.streamId, topic: message.topic,
367
+ unreadMessageIds: [message.id]),
368
+ ]);
369
+
370
+ testWidgets ('smoke test on modern server' , (WidgetTester tester) async {
371
+ final narrow = TopicNarrow .ofMessage (message);
372
+ await setupMessageListPage (tester,
373
+ narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
374
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
375
+
376
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
377
+ processedCount: 11 , updatedCount: 3 ,
378
+ firstProcessedId: null , lastProcessedId: null ,
379
+ foundOldest: true , foundNewest: true ).toJson ());
380
+ await tester.tap (find.byType (MarkAsReadWidget ));
381
+ final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
382
+ check (connection.lastRequest).isA< http.Request > ()
383
+ ..method.equals ('POST' )
384
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
385
+ ..bodyFields.deepEquals ({
386
+ 'anchor' : 'oldest' ,
387
+ 'include_anchor' : 'false' ,
388
+ 'num_before' : '0' ,
389
+ 'num_after' : '1000' ,
390
+ 'narrow' : jsonEncode (apiNarrow),
391
+ 'op' : 'add' ,
392
+ 'flag' : 'read' ,
393
+ });
394
+
395
+ await tester.pumpAndSettle (); // process pending timers
396
+ });
397
+
398
+ testWidgets ('pagination' , (WidgetTester tester) async {
399
+ // Check that `lastProcessedId` returned from an initial
400
+ // response is used as `anchorId` for the subsequent request.
401
+ final narrow = TopicNarrow .ofMessage (message);
402
+ await setupMessageListPage (tester,
403
+ narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
404
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
405
+
406
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
407
+ processedCount: 1000 , updatedCount: 890 ,
408
+ firstProcessedId: 1 , lastProcessedId: 1989 ,
409
+ foundOldest: true , foundNewest: false ).toJson ());
410
+ await tester.tap (find.byType (MarkAsReadWidget ));
411
+ check (connection.lastRequest).isA< http.Request > ()
412
+ ..method.equals ('POST' )
413
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
414
+ ..bodyFields['anchor' ].equals ('oldest' );
415
+
416
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
417
+ processedCount: 20 , updatedCount: 10 ,
418
+ firstProcessedId: 2000 , lastProcessedId: 2023 ,
419
+ foundOldest: false , foundNewest: true ).toJson ());
420
+ await tester.pumpAndSettle ();
421
+ check (find.bySubtype <SnackBar >().evaluate ()).length.equals (1 );
422
+ check (connection.lastRequest).isA< http.Request > ()
423
+ ..method.equals ('POST' )
424
+ ..url.path.equals ('/api/v1/messages/flags/narrow' )
425
+ ..bodyFields['anchor' ].equals ('1989' );
426
+ });
427
+
428
+ testWidgets ('markNarrowAsRead on mark-all-as-read when Unreads.oldUnreadsMissing: true' , (tester) async {
429
+ const narrow = CombinedFeedNarrow ();
430
+ await setupMessageListPage (tester,
431
+ narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
432
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
433
+ store.unreads.oldUnreadsMissing = true ;
434
+
435
+ connection.prepare (json: UpdateMessageFlagsForNarrowResult (
436
+ processedCount: 11 , updatedCount: 3 ,
437
+ firstProcessedId: null , lastProcessedId: null ,
438
+ foundOldest: true , foundNewest: true ).toJson ());
439
+ await tester.tap (find.byType (MarkAsReadWidget ));
440
+ await tester.pumpAndSettle ();
441
+ check (store.unreads.oldUnreadsMissing).isFalse ();
442
+ });
443
+
444
+ testWidgets ('catch-all api errors' , (WidgetTester tester) async {
445
+ final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
446
+ const narrow = CombinedFeedNarrow ();
447
+ await setupMessageListPage (tester,
448
+ narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
449
+ check (isMarkAsReadButtonVisible (tester)).isTrue ();
450
+
451
+ connection.prepare (exception: http.ClientException ('Oops' ));
452
+ await tester.tap (find.byType (MarkAsReadWidget ));
453
+ await tester.pumpAndSettle ();
454
+ checkErrorDialog (tester,
455
+ expectedTitle: zulipLocalizations.errorMarkAsReadFailedTitle,
456
+ expectedMessage: 'NetworkException: Oops (ClientException: Oops)' );
457
+ });
458
+ });
459
+ });
460
+
297
461
group ('recipient headers' , () {
298
462
group ('StreamMessageRecipientHeader' , () {
299
463
final stream = eg.stream (name: 'stream name' );
@@ -817,168 +981,4 @@ void main() {
817
981
..status.equals (AnimationStatus .dismissed);
818
982
});
819
983
});
820
-
821
- group ('MarkAsReadWidget' , () {
822
- bool isMarkAsReadButtonVisible (WidgetTester tester) {
823
- final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
824
- final finder = find.text (
825
- zulipLocalizations.markAllAsReadLabel).hitTestable ();
826
- return finder.evaluate ().isNotEmpty;
827
- }
828
-
829
- testWidgets ('from read to unread' , (WidgetTester tester) async {
830
- final message = eg.streamMessage (flags: [MessageFlag .read]);
831
- await setupMessageListPage (tester, messages: [message]);
832
- check (isMarkAsReadButtonVisible (tester)).isFalse ();
833
-
834
- await store.handleEvent (eg.updateMessageFlagsRemoveEvent (
835
- MessageFlag .read, [message]));
836
- await tester.pumpAndSettle ();
837
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
838
- });
839
-
840
- testWidgets ('from unread to read' , (WidgetTester tester) async {
841
- final message = eg.streamMessage (flags: []);
842
- final unreadMsgs = eg.unreadMsgs (streams: [
843
- UnreadStreamSnapshot (topic: message.topic, streamId: message.streamId, unreadMessageIds: [message.id])
844
- ]);
845
- await setupMessageListPage (tester, messages: [message], unreadMsgs: unreadMsgs);
846
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
847
-
848
- await store.handleEvent (UpdateMessageFlagsAddEvent (
849
- id: 1 ,
850
- flag: MessageFlag .read,
851
- messages: [message.id],
852
- all: false ,
853
- ));
854
- await tester.pumpAndSettle ();
855
- check (isMarkAsReadButtonVisible (tester)).isFalse ();
856
- });
857
-
858
- testWidgets ("messages don't shift position" , (WidgetTester tester) async {
859
- final message = eg.streamMessage (flags: []);
860
- final unreadMsgs = eg.unreadMsgs (streams: [
861
- UnreadStreamSnapshot (topic: message.topic, streamId: message.streamId,
862
- unreadMessageIds: [message.id])
863
- ]);
864
- await setupMessageListPage (tester,
865
- messages: [message], unreadMsgs: unreadMsgs);
866
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
867
- check (tester.widgetList (find.byType (MessageItem ))).length.equals (1 );
868
- final before = tester.getTopLeft (find.byType (MessageItem )).dy;
869
-
870
- await store.handleEvent (UpdateMessageFlagsAddEvent (
871
- id: 1 ,
872
- flag: MessageFlag .read,
873
- messages: [message.id],
874
- all: false ,
875
- ));
876
- await tester.pumpAndSettle ();
877
- check (isMarkAsReadButtonVisible (tester)).isFalse ();
878
- check (tester.widgetList (find.byType (MessageItem ))).length.equals (1 );
879
- final after = tester.getTopLeft (find.byType (MessageItem )).dy;
880
- check (after).equals (before);
881
- });
882
-
883
- group ('onPressed behavior' , () {
884
- // The markNarrowAsRead function has detailed unit tests of its own.
885
- // These tests cover functionality that's outside that function,
886
- // and a couple of smoke tests showing this button is wired up to it.
887
-
888
- final message = eg.streamMessage (flags: []);
889
- final unreadMsgs = eg.unreadMsgs (streams: [
890
- UnreadStreamSnapshot (streamId: message.streamId, topic: message.topic,
891
- unreadMessageIds: [message.id]),
892
- ]);
893
-
894
- testWidgets ('smoke test on modern server' , (WidgetTester tester) async {
895
- final narrow = TopicNarrow .ofMessage (message);
896
- await setupMessageListPage (tester,
897
- narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
898
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
899
-
900
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
901
- processedCount: 11 , updatedCount: 3 ,
902
- firstProcessedId: null , lastProcessedId: null ,
903
- foundOldest: true , foundNewest: true ).toJson ());
904
- await tester.tap (find.byType (MarkAsReadWidget ));
905
- final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
906
- check (connection.lastRequest).isA< http.Request > ()
907
- ..method.equals ('POST' )
908
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
909
- ..bodyFields.deepEquals ({
910
- 'anchor' : 'oldest' ,
911
- 'include_anchor' : 'false' ,
912
- 'num_before' : '0' ,
913
- 'num_after' : '1000' ,
914
- 'narrow' : jsonEncode (apiNarrow),
915
- 'op' : 'add' ,
916
- 'flag' : 'read' ,
917
- });
918
-
919
- await tester.pumpAndSettle (); // process pending timers
920
- });
921
-
922
- testWidgets ('pagination' , (WidgetTester tester) async {
923
- // Check that `lastProcessedId` returned from an initial
924
- // response is used as `anchorId` for the subsequent request.
925
- final narrow = TopicNarrow .ofMessage (message);
926
- await setupMessageListPage (tester,
927
- narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
928
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
929
-
930
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
931
- processedCount: 1000 , updatedCount: 890 ,
932
- firstProcessedId: 1 , lastProcessedId: 1989 ,
933
- foundOldest: true , foundNewest: false ).toJson ());
934
- await tester.tap (find.byType (MarkAsReadWidget ));
935
- check (connection.lastRequest).isA< http.Request > ()
936
- ..method.equals ('POST' )
937
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
938
- ..bodyFields['anchor' ].equals ('oldest' );
939
-
940
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
941
- processedCount: 20 , updatedCount: 10 ,
942
- firstProcessedId: 2000 , lastProcessedId: 2023 ,
943
- foundOldest: false , foundNewest: true ).toJson ());
944
- await tester.pumpAndSettle ();
945
- check (find.bySubtype <SnackBar >().evaluate ()).length.equals (1 );
946
- check (connection.lastRequest).isA< http.Request > ()
947
- ..method.equals ('POST' )
948
- ..url.path.equals ('/api/v1/messages/flags/narrow' )
949
- ..bodyFields['anchor' ].equals ('1989' );
950
- });
951
-
952
- testWidgets ('markNarrowAsRead on mark-all-as-read when Unreads.oldUnreadsMissing: true' , (tester) async {
953
- const narrow = CombinedFeedNarrow ();
954
- await setupMessageListPage (tester,
955
- narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
956
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
957
- store.unreads.oldUnreadsMissing = true ;
958
-
959
- connection.prepare (json: UpdateMessageFlagsForNarrowResult (
960
- processedCount: 11 , updatedCount: 3 ,
961
- firstProcessedId: null , lastProcessedId: null ,
962
- foundOldest: true , foundNewest: true ).toJson ());
963
- await tester.tap (find.byType (MarkAsReadWidget ));
964
- await tester.pumpAndSettle ();
965
- check (store.unreads.oldUnreadsMissing).isFalse ();
966
- });
967
-
968
- testWidgets ('catch-all api errors' , (WidgetTester tester) async {
969
- final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
970
- const narrow = CombinedFeedNarrow ();
971
- await setupMessageListPage (tester,
972
- narrow: narrow, messages: [message], unreadMsgs: unreadMsgs);
973
- check (isMarkAsReadButtonVisible (tester)).isTrue ();
974
-
975
- connection.prepare (exception: http.ClientException ('Oops' ));
976
- await tester.tap (find.byType (MarkAsReadWidget ));
977
- await tester.pumpAndSettle ();
978
- checkErrorDialog (tester,
979
- expectedTitle: zulipLocalizations.errorMarkAsReadFailedTitle,
980
- expectedMessage: 'NetworkException: Oops (ClientException: Oops)' );
981
- });
982
- });
983
- });
984
984
}
0 commit comments