From b1c06415cb2eb939393f53e3b8c1bc7535a628a4 Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Fri, 28 Apr 2023 16:10:26 -0400 Subject: [PATCH 1/2] test: Add example data for User --- test/example_data.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/example_data.dart b/test/example_data.dart index c9d314bb38..aa335d1760 100644 --- a/test/example_data.dart +++ b/test/example_data.dart @@ -7,6 +7,27 @@ final Uri realmUrl = Uri.parse('https://chat.example/'); const String recentZulipVersion = '6.1'; const int recentZulipFeatureLevel = 164; +User user({int? userId, String? fullName}) { + return User( + userId: userId ?? 123, // TODO generate example IDs + deliveryEmailStaleDoNotUse: 'name@example.com', + email: 'name@example.com', // TODO generate example emails + fullName: fullName ?? 'A user',// TODO generate example names + dateJoined: '2023-04-28', + isActive: true, + isOwner: false, + isAdmin: false, + isGuest: false, + isBillingAdmin: false, + isBot: false, + role: 400, + timezone: 'UTC', + avatarUrl: null, + avatarVersion: 0, + profileData: null, + ); +} + final Account selfAccount = Account( id: 1001, realmUrl: realmUrl, From 8895ce8d3977354ad4b899f1948f9d48a3e18987 Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Fri, 14 Apr 2023 16:39:25 -0700 Subject: [PATCH 2/2] autocomplete: Add and test MentionAutocompleteQuery This is a small step toward #49, without changing any UI. Here we have a simple function `testUser` to test whether a given User matches a query. Related: #49 --- lib/model/autocomplete.dart | 42 +++++++++++++++++++++++++++++ test/model/autocomplete_test.dart | 44 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 lib/model/autocomplete.dart create mode 100644 test/model/autocomplete_test.dart diff --git a/lib/model/autocomplete.dart b/lib/model/autocomplete.dart new file mode 100644 index 0000000000..d35ce8f26a --- /dev/null +++ b/lib/model/autocomplete.dart @@ -0,0 +1,42 @@ +import '../api/model/model.dart'; + +class MentionAutocompleteQuery { + MentionAutocompleteQuery(this.raw) + : _lowercaseWords = raw.toLowerCase().split(' '); + + final String raw; + + final List _lowercaseWords; + + bool testUser(User user) { + // TODO test email too, not just name + // TODO test with diacritics stripped, where appropriate + + // TODO cache, elsewhere + final List nameWords = user.fullName.toLowerCase().split(' '); + + int nameWordsIndex = 0; + int queryWordsIndex = 0; + while (true) { + if (queryWordsIndex == _lowercaseWords.length) { + return true; + } + if (nameWordsIndex == nameWords.length) { + return false; + } + + if (nameWords[nameWordsIndex].startsWith(_lowercaseWords[queryWordsIndex])) { + queryWordsIndex++; + } + nameWordsIndex++; + } + } + + @override + bool operator ==(Object other) { + return other is MentionAutocompleteQuery && other.raw == raw; + } + + @override + int get hashCode => Object.hash('MentionAutocompleteQuery', raw); +} diff --git a/test/model/autocomplete_test.dart b/test/model/autocomplete_test.dart new file mode 100644 index 0000000000..29b7530d56 --- /dev/null +++ b/test/model/autocomplete_test.dart @@ -0,0 +1,44 @@ +import 'package:checks/checks.dart'; +import 'package:test/scaffolding.dart'; +import 'package:zulip/api/model/model.dart'; +import 'package:zulip/model/autocomplete.dart'; + +import '../example_data.dart' as eg; + +void main() { + test('MentionAutocompleteQuery.testUser', () { + doCheck(String rawQuery, User user, bool expected) { + final result = MentionAutocompleteQuery(rawQuery).testUser(user); + expected ? check(result).isTrue() : check(result).isFalse(); + } + + doCheck('', eg.user(fullName: 'Full Name'), true); + doCheck('', eg.user(fullName: ''), true); // Unlikely case, but should not crash + doCheck('Full Name', eg.user(fullName: 'Full Name'), true); + doCheck('full name', eg.user(fullName: 'Full Name'), true); + doCheck('Full Name', eg.user(fullName: 'full name'), true); + doCheck('Full', eg.user(fullName: 'Full Name'), true); + doCheck('Name', eg.user(fullName: 'Full Name'), true); + doCheck('Full Name', eg.user(fullName: 'Fully Named'), true); + doCheck('Full Four', eg.user(fullName: 'Full Name Four Words'), true); + doCheck('Name Words', eg.user(fullName: 'Full Name Four Words'), true); + doCheck('Full F', eg.user(fullName: 'Full Name Four Words'), true); + doCheck('F Four', eg.user(fullName: 'Full Name Four Words'), true); + doCheck('full full', eg.user(fullName: 'Full Full Name'), true); + doCheck('full full', eg.user(fullName: 'Full Name Full'), true); + + doCheck('F', eg.user(fullName: ''), false); // Unlikely case, but should not crash + doCheck('Fully Named', eg.user(fullName: 'Full Name'), false); + doCheck('Full Name', eg.user(fullName: 'Full'), false); + doCheck('Full Name', eg.user(fullName: 'Name'), false); + doCheck('ull ame', eg.user(fullName: 'Full Name'), false); + doCheck('ull Name', eg.user(fullName: 'Full Name'), false); + doCheck('Full ame', eg.user(fullName: 'Full Name'), false); + doCheck('Full Full', eg.user(fullName: 'Full Name'), false); + doCheck('Name Name', eg.user(fullName: 'Full Name'), false); + doCheck('Name Full', eg.user(fullName: 'Full Name'), false); + doCheck('Name Four Full Words', eg.user(fullName: 'Full Name Four Words'), false); + doCheck('F Full', eg.user(fullName: 'Full Name Four Words'), false); + doCheck('Four F', eg.user(fullName: 'Full Name Four Words'), false); + }); +}