@@ -5,6 +5,7 @@ import 'package:checks/checks.dart';
55import  'package:fake_async/fake_async.dart' ;
66import  'package:flutter/cupertino.dart' ;
77import  'package:test/scaffolding.dart' ;
8+ import  'package:zulip/api/model/initial_snapshot.dart' ;
89import  'package:zulip/api/model/model.dart' ;
910import  'package:zulip/model/autocomplete.dart' ;
1011import  'package:zulip/model/narrow.dart' ;
@@ -277,12 +278,12 @@ void main() {
277278
278279  group ('MentionAutocompleteView recomputes results and does it only one time' , () {
279280    Future <void > doCheck ({
281+       Narrow  narrow =  const  CombinedFeedNarrow (),
280282      required  List <User > users,
281283      required  String  rawQuery,
282284      required  Future <void > Function (PerAccountStore  store) act,
283285      required  void  Function (Iterable <MentionAutocompleteResult >) expect,
284286    }) async  {
285-       const  narrow =  CombinedFeedNarrow ();
286287      final  store =  eg.store ();
287288      await  store.addUsers (users);
288289      final  view =  MentionAutocompleteView .init (store:  store, narrow:  narrow);
@@ -380,6 +381,28 @@ void main() {
380381        expect:  expect,
381382      );
382383    });
384+ 
385+     test ('MessageEvent' , () async  {
386+       final  users =  generateUsers (count:  1500 );
387+ 
388+       Future <void > act (PerAccountStore  store) async  {
389+         await  store.addMessage (eg.dmMessage (from:  eg.selfUser, to:  [users[100 ]]));
390+       }
391+ 
392+       void  expect (Iterable <MentionAutocompleteResult > results) {
393+         check (results.elementAt (0 ))
394+         .isA <UserMentionAutocompleteResult >()
395+         .userId.equals (100 );
396+       }
397+ 
398+       await  doCheck (
399+         narrow:  DmNarrow .withUser (100 , selfUserId:  eg.selfUser.userId),
400+         users:  users,
401+         rawQuery:  '' ,
402+         act:  act,
403+         expect:  expect,
404+       );
405+     });
383406  });
384407
385408  group ('MentionAutocompleteQuery.testUser' , () {
@@ -426,4 +449,157 @@ void main() {
426449      doCheck ('Four F' , eg.user (fullName:  'Full Name Four Words' ), false );
427450    });
428451  });
452+ 
453+   group ('MentionAutocompleteView users results' , () {
454+     late  PerAccountStore  store;
455+     late  MentionAutocompleteView  view;
456+ 
457+     Future <void > prepare ({
458+       required  List <User > users,
459+       required  List <RecentDmConversation > dmConversations,
460+       required  Narrow  narrow,
461+     }) async  {
462+       store =  eg.store (initialSnapshot:  eg.initialSnapshot (
463+         recentPrivateConversations:  dmConversations));
464+       await  store.addUsers (users);
465+       view =  MentionAutocompleteView .init (store:  store, narrow:  narrow);
466+     }
467+ 
468+     group ('MentionAutocompleteView.compareByDms' , () {
469+       test ('has DMs with userA and userB, latest with userA, prioritizes userA' , () async  {
470+         await  prepare (
471+           users:  [],
472+           dmConversations:  [
473+             RecentDmConversation (userIds:  [1 ],    maxMessageId:  200 ),
474+             RecentDmConversation (userIds:  [1 , 2 ], maxMessageId:  100 ),
475+           ],
476+           narrow:  const  CombinedFeedNarrow (),
477+         );
478+ 
479+         final  userA =  eg.user (userId:  1 );
480+         final  userB =  eg.user (userId:  2 );
481+         final  compareAB =  view.compareByDms (userA, userB);
482+         check (compareAB).isNegative ();
483+       });
484+ 
485+       test ('has DMs with userA and userB, latest with userB, prioritizes userB' , () async  {
486+         await  prepare (
487+           users:  [],
488+           dmConversations:  [
489+             RecentDmConversation (userIds:  [2 ],    maxMessageId:  200 ),
490+             RecentDmConversation (userIds:  [1 , 2 ], maxMessageId:  100 ),
491+           ],
492+           narrow:  const  CombinedFeedNarrow (),
493+         );
494+ 
495+         final  userA =  eg.user (userId:  1 );
496+         final  userB =  eg.user (userId:  2 );
497+         final  compareAB =  view.compareByDms (userA, userB);
498+         check (compareAB).isGreaterThan (0 );
499+       });
500+ 
501+       test ('has DMs with userA and userB, equally recent, prioritizes neither' , () async  {
502+         await  prepare (
503+           users:  [],
504+           dmConversations:  [
505+             RecentDmConversation (userIds:  [1 , 2 ], maxMessageId:  100 ),
506+           ],
507+           narrow:  const  CombinedFeedNarrow (),
508+         );
509+ 
510+         final  userA =  eg.user (userId:  1 );
511+         final  userB =  eg.user (userId:  2 );
512+         final  compareAB =  view.compareByDms (userA, userB);
513+         check (compareAB).equals (0 );
514+       });
515+ 
516+       test ('has DMs with userA but not userB, prioritizes userA' , () async  {
517+         await  prepare (
518+           users:  [],
519+           dmConversations:  [
520+             RecentDmConversation (userIds:  [1 ], maxMessageId:  100 ),
521+           ],
522+           narrow:  const  CombinedFeedNarrow (),
523+         );
524+ 
525+         final  userA =  eg.user (userId:  1 );
526+         final  userB =  eg.user (userId:  2 );
527+         final  compareAB =  view.compareByDms (userA, userB);
528+         check (compareAB).isNegative ();
529+       });
530+ 
531+       test ('has DMs with userB but not userA, prioritizes userB' , () async  {
532+         await  prepare (
533+           users:  [],
534+           dmConversations:  [
535+             RecentDmConversation (userIds:  [2 ], maxMessageId:  100 ),
536+           ],
537+           narrow:  const  CombinedFeedNarrow (),
538+         );
539+ 
540+         final  userA =  eg.user (userId:  1 );
541+         final  userB =  eg.user (userId:  2 );
542+         final  compareAB =  view.compareByDms (userA, userB);
543+         check (compareAB).isGreaterThan (0 );
544+       });
545+ 
546+       test ('doesn\' t have DMs with userA or userB, prioritizes neither' , () async  {
547+         await  prepare (
548+           users:  [],
549+           dmConversations:  [],
550+           narrow:  const  CombinedFeedNarrow (),
551+         );
552+ 
553+         final  userA =  eg.user (userId:  1 );
554+         final  userB =  eg.user (userId:  2 );
555+         final  compareAB =  view.compareByDms (userA, userB);
556+         check (compareAB).equals (0 );
557+       });
558+     });
559+ 
560+     test ('autocomplete suggests relevant users in the following order: ' 
561+       '1. Users most recent in the DM conversations' , () async  {
562+       final  users =  [
563+         eg.user (userId:  1 ),
564+         eg.user (userId:  2 ),
565+         eg.user (userId:  3 ),
566+         eg.user (userId:  4 ),
567+         eg.user (userId:  5 ),
568+       ];
569+ 
570+       final  dmConversations =  [
571+         RecentDmConversation (userIds:  [4 ],    maxMessageId:  300 ),
572+         RecentDmConversation (userIds:  [1 ],    maxMessageId:  200 ),
573+         RecentDmConversation (userIds:  [1 , 2 ], maxMessageId:  100 ),
574+       ];
575+ 
576+       Future <void > checkResultsIn (Narrow  narrow, {required  List <int > expected}) async  {
577+         await  prepare (users:  users, dmConversations:  dmConversations, narrow:  narrow);
578+ 
579+         bool  done =  false ;
580+         view.addListener (() { done =  true ; });
581+         view.query =  MentionAutocompleteQuery ('' );
582+         await  Future (() {});
583+         check (done).isTrue ();
584+         final  results =  view.results
585+           .map ((e) =>  (e as  UserMentionAutocompleteResult ).userId)
586+           .toList ();
587+         check (results).deepEquals (expected);
588+       }
589+ 
590+       const  streamNarrow =  StreamNarrow (1 );
591+       await  checkResultsIn (streamNarrow, expected:  [4 , 1 , 2 , 3 , 5 ]);
592+ 
593+       const  topicNarrow =  TopicNarrow (1 , 'topic' );
594+       await  checkResultsIn (topicNarrow, expected:  [4 , 1 , 2 , 3 , 5 ]);
595+ 
596+       final  dmNarrow =  DmNarrow (allRecipientIds:  [eg.selfUser.userId], selfUserId:  eg.selfUser.userId);
597+       await  checkResultsIn (dmNarrow, expected:  [4 , 1 , 2 , 3 , 5 ]);
598+ 
599+       const  allMessagesNarrow =  CombinedFeedNarrow ();
600+       // Results are in the original order as we do not sort them for 
601+       // [AllMessagesNarrow] because we can not access autocomplete for now. 
602+       await  checkResultsIn (allMessagesNarrow, expected:  [1 , 2 , 3 , 4 , 5 ]);
603+     });
604+   });
429605}
0 commit comments