@@ -5,9 +5,11 @@ import 'package:checks/checks.dart';
5
5
import 'package:fake_async/fake_async.dart' ;
6
6
import 'package:flutter/cupertino.dart' ;
7
7
import 'package:test/scaffolding.dart' ;
8
+ import 'package:zulip/api/model/initial_snapshot.dart' ;
8
9
import 'package:zulip/api/model/model.dart' ;
9
10
import 'package:zulip/model/autocomplete.dart' ;
10
11
import 'package:zulip/model/narrow.dart' ;
12
+ import 'package:zulip/model/store.dart' ;
11
13
import 'package:zulip/widgets/compose_box.dart' ;
12
14
13
15
import '../example_data.dart' as eg;
@@ -318,4 +320,141 @@ void main() {
318
320
doCheck ('Four F' , eg.user (fullName: 'Full Name Four Words' ), false );
319
321
});
320
322
});
323
+
324
+ group ('MentionAutocompleteView sorting users results' , () {
325
+ late PerAccountStore store;
326
+
327
+ Future <void > prepare ({
328
+ List <User > users = const [],
329
+ List <RecentDmConversation > dmConversations = const [],
330
+ }) async {
331
+ store = eg.store (initialSnapshot: eg.initialSnapshot (
332
+ recentPrivateConversations: dmConversations));
333
+ await store.addUsers (users);
334
+ }
335
+
336
+ group ('MentionAutocompleteView.compareByDms' , () {
337
+ test ('has DMs with userA and userB, latest with userA, prioritizes userA' , () async {
338
+ await prepare (
339
+ dmConversations: [
340
+ RecentDmConversation (userIds: [1 ], maxMessageId: 200 ),
341
+ RecentDmConversation (userIds: [1 , 2 ], maxMessageId: 100 ),
342
+ ],
343
+ );
344
+
345
+ final userA = eg.user (userId: 1 );
346
+ final userB = eg.user (userId: 2 );
347
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
348
+ check (compareAB).isNegative ();
349
+ });
350
+
351
+ test ('has DMs with userA and userB, latest with userB, prioritizes userB' , () async {
352
+ await prepare (
353
+ dmConversations: [
354
+ RecentDmConversation (userIds: [2 ], maxMessageId: 200 ),
355
+ RecentDmConversation (userIds: [1 , 2 ], maxMessageId: 100 ),
356
+ ],
357
+ );
358
+
359
+ final userA = eg.user (userId: 1 );
360
+ final userB = eg.user (userId: 2 );
361
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
362
+ check (compareAB).isGreaterThan (0 );
363
+ });
364
+
365
+ test ('has DMs with userA and userB, equally recent, prioritizes neither' , () async {
366
+ await prepare (
367
+ dmConversations: [
368
+ RecentDmConversation (userIds: [1 , 2 ], maxMessageId: 100 ),
369
+ ],
370
+ );
371
+
372
+ final userA = eg.user (userId: 1 );
373
+ final userB = eg.user (userId: 2 );
374
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
375
+ check (compareAB).equals (0 );
376
+ });
377
+
378
+ test ('has DMs with userA but not userB, prioritizes userA' , () async {
379
+ await prepare (
380
+ dmConversations: [
381
+ RecentDmConversation (userIds: [1 ], maxMessageId: 100 ),
382
+ ],
383
+ );
384
+
385
+ final userA = eg.user (userId: 1 );
386
+ final userB = eg.user (userId: 2 );
387
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
388
+ check (compareAB).isNegative ();
389
+ });
390
+
391
+ test ('has DMs with userB but not userA, prioritizes userB' , () async {
392
+ await prepare (
393
+ dmConversations: [
394
+ RecentDmConversation (userIds: [2 ], maxMessageId: 100 ),
395
+ ],
396
+ );
397
+
398
+ final userA = eg.user (userId: 1 );
399
+ final userB = eg.user (userId: 2 );
400
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
401
+ check (compareAB).isGreaterThan (0 );
402
+ });
403
+
404
+ test ('doesn\' t have DMs with userA or userB, prioritizes neither' , () async {
405
+ await prepare (dmConversations: []);
406
+
407
+ final userA = eg.user (userId: 1 );
408
+ final userB = eg.user (userId: 2 );
409
+ final compareAB = MentionAutocompleteView .compareByDms (userA, userB, store: store);
410
+ check (compareAB).equals (0 );
411
+ });
412
+ });
413
+
414
+ test ('autocomplete suggests relevant users in the following order: '
415
+ '1. Users most recent in the DM conversations' , () async {
416
+ final users = [
417
+ eg.user (userId: 1 ),
418
+ eg.user (userId: 2 ),
419
+ eg.user (userId: 3 ),
420
+ eg.user (userId: 4 ),
421
+ eg.user (userId: 5 ),
422
+ ];
423
+
424
+ final dmConversations = [
425
+ RecentDmConversation (userIds: [4 ], maxMessageId: 300 ),
426
+ RecentDmConversation (userIds: [1 ], maxMessageId: 200 ),
427
+ RecentDmConversation (userIds: [1 , 2 ], maxMessageId: 100 ),
428
+ ];
429
+
430
+ Future <void > checkResultsIn (Narrow narrow, {required List <int > expected}) async {
431
+ await prepare (users: users, dmConversations: dmConversations);
432
+ final view = MentionAutocompleteView .init (store: store, narrow: narrow);
433
+
434
+ bool done = false ;
435
+ view.addListener (() { done = true ; });
436
+ view.query = MentionAutocompleteQuery ('' );
437
+ await Future (() {});
438
+ check (done).isTrue ();
439
+ final results = view.results
440
+ .map ((e) => (e as UserMentionAutocompleteResult ).userId)
441
+ .toList ();
442
+ check (results).deepEquals (expected);
443
+ }
444
+
445
+ const streamNarrow = StreamNarrow (1 );
446
+ await checkResultsIn (streamNarrow, expected: [4 , 1 , 2 , 3 , 5 ]);
447
+
448
+ const topicNarrow = TopicNarrow (1 , 'topic' );
449
+ await checkResultsIn (topicNarrow, expected: [4 , 1 , 2 , 3 , 5 ]);
450
+
451
+ final dmNarrow = DmNarrow (allRecipientIds: [eg.selfUser.userId], selfUserId: eg.selfUser.userId);
452
+ await checkResultsIn (dmNarrow, expected: [4 , 1 , 2 , 3 , 5 ]);
453
+
454
+ const allMessagesNarrow = CombinedFeedNarrow ();
455
+ // Results are in the original order as we do not sort them for
456
+ // [CombinedFeedNarrow] because we can not access autocomplete for now.
457
+ await checkResultsIn (allMessagesNarrow, expected: [1 , 2 , 3 , 4 , 5 ]);
458
+ });
459
+ });
321
460
}
0 commit comments